#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-12-08 14:49-0200\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. Put one translator per line, in the form NAME , YEAR1, YEAR2 msgctxt "_" msgid "translator-credits" msgstr "" #. (itstool) path: info/title #: book.translate.xml:140 msgid "FreeBSD Architecture Handbook" msgstr "" #. (itstool) path: info/author #: book.translate.xml:143 msgid "The FreeBSD Documentation Project" msgstr "" #. (itstool) path: info/pubdate #. (itstool) path: info/releaseinfo #: book.translate.xml:145 book.translate.xml:224 msgid "" "$FreeBSD: head/en_US.ISO8859-1/books/arch-handbook/book.xml 51016 2017-10-01 " "12:11:13Z wosch $" msgstr "" #. (itstool) path: info/copyright #: book.translate.xml:147 msgid "" "2000 2001 2002 2003 " "2004 2005 2006 2012 " "2013 The FreeBSD Documentation Project" msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:161 msgid "FreeBSD is a registered trademark of the FreeBSD Foundation." msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:163 msgid "" "UNIX is a registered trademark of The Open Group in the United States and " "other countries." msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:165 msgid "" "Apple, AirPort, FireWire, iMac, iPhone, iPad, Mac, Macintosh, Mac OS, " "Quicktime, and TrueType are trademarks of Apple Inc., registered in the U.S. " "and other countries." msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:170 msgid "" "Microsoft, IntelliMouse, MS-DOS, Outlook, Windows, Windows Media and Windows " "NT are either registered trademarks or trademarks of Microsoft Corporation " "in the United States and/or other countries." msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:174 msgid "" "Many of the designations used by manufacturers and sellers to distinguish " "their products are claimed as trademarks. Where those designations appear in " "this document, and the FreeBSD Project was aware of the trademark claim, the " "designations have been followed by the or the ® symbol." msgstr "" #. (itstool) path: legalnotice/title #: book.translate.xml:184 msgid "Copyright" msgstr "" #. (itstool) path: legalnotice/para #: book.translate.xml:186 msgid "" "Redistribution and use in source (XML DocBook) and 'compiled' forms (XML, " "HTML, PDF, PostScript, RTF and so forth) with or without modification, are " "permitted provided that the following conditions are met:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:193 msgid "" "Redistributions of source code (XML DocBook) must retain the above copyright " "notice, this list of conditions and the following disclaimer as the first " "lines of this file unmodified." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:199 book.translate.xml:4356 msgid "" "Redistributions in compiled form (transformed to other DTDs, converted to " "PDF, PostScript, RTF and other formats) 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." msgstr "" #. (itstool) path: important/para #: book.translate.xml:208 msgid "" "THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD DOCUMENTATION PROJECT \"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 FREEBSD DOCUMENTATION PROJECT " "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 DOCUMENTATION, EVEN IF ADVISED OF " "THE POSSIBILITY OF SUCH DAMAGE." msgstr "" #. (itstool) path: abstract/para #: book.translate.xml:227 msgid "" "Welcome to the FreeBSD Architecture Handbook. This manual is a " "work in progress and is the work of many individuals. " "Many sections do not yet exist and some of those that do exist need to be " "updated. If you are interested in helping with this project, send email to " "the FreeBSD documentation project mailing list." msgstr "" #. (itstool) path: abstract/para #: book.translate.xml:234 msgid "" "The latest version of this document is always available from the FreeBSD World Wide Web server. " "It may also be downloaded in a variety of formats and compression options " "from the FreeBSD " "FTP server or one of the numerous mirror sites." msgstr "" #. (itstool) path: part/title #: book.translate.xml:243 msgid "Kernel" msgstr "" #. (itstool) path: info/title #: book.translate.xml:259 msgid "Bootstrapping and Kernel Initialization" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:262 msgid "" " Sergey Lyubka Contributed by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:274 msgid "" " Sergio Andrés Gómez del Real Updated and enhanced by " msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:287 book.translate.xml:4383 book.translate.xml:16481 #: book.translate.xml:19448 msgid "Synopsis" msgstr "" #. (itstool) path: sect1/indexterm #. (itstool) path: para/indexterm #: book.translate.xml:289 book.translate.xml:20796 msgid "BIOS" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:290 msgid "firmware" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:291 msgid "POST" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:292 msgid "IA-32" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:293 msgid "booting" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:294 msgid "system initialization" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:295 msgid "" "This chapter is an overview of the boot and system initialization processes, " "starting from the BIOS (firmware) POST, to the first user process creation. Since the initial steps of " "system startup are very architecture dependent, the IA-32 architecture is " "used as an example." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:301 msgid "" "The FreeBSD boot process can be surprisingly complex. After control is " "passed from the BIOS, a considerable amount of low-level " "configuration must be done before the kernel can be loaded and executed. " "This setup must be done in a simple and flexible manner, allowing the user a " "great deal of customization possibilities." msgstr "" #. (itstool) path: sect1/title #. (itstool) path: sect2/title #: book.translate.xml:310 book.translate.xml:23491 msgid "Overview" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:312 msgid "" "The boot process is an extremely machine-dependent activity. Not only must " "code be written for every computer architecture, but there may also be " "multiple types of booting on the same architecture. For example, a directory " "listing of /usr/src/sys/boot reveals a great amount of " "architecture-dependent code. There is a directory for each of the various " "supported architectures. In the x86-specific i386 " "directory, there are subdirectories for different boot standards like " "mbr (Master Boot Record), gpt " "(GUID Partition Table), and efi " "(Extensible Firmware Interface). Each boot standard has its own conventions " "and data structures. The example that follows shows booting an x86 computer " "from an MBR hard drive with the FreeBSD boot0 multi-boot loader stored in the very first sector. That boot code " "starts the FreeBSD three-stage boot process." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:331 msgid "" "The key to understanding this process is that it is a series of stages of " "increasing complexity. These stages are boot1, " "boot2, and loader (see " "boot8 for more detail). The boot system executes each stage in " "sequence. The last stage, loader, is responsible for " "loading the FreeBSD kernel. Each stage is examined in the following sections." "" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:340 msgid "" "Here is an example of the output generated by the different boot stages. " "Actual output may differ from machine to machine:" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:348 msgid "FreeBSD Component" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:349 msgid "Output (may vary)" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:353 msgid "boot0" msgstr "" #. (itstool) path: entry/screen #: book.translate.xml:354 #, no-wrap msgid "F1 FreeBSD\n" "F2 BSD\n" "F5 Disk 2" msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:361 msgid "" "This prompt will appear if the user presses a key just after selecting an OS " "to boot at the boot0 stage." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:360 msgid "boot2 <_:footnote-1/>" msgstr "" #. (itstool) path: entry/screen #: book.translate.xml:365 #, no-wrap msgid ">>FreeBSD/i386 BOOT\n" "Default: 1:ad(1,a)/boot/loader\n" "boot:" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:371 msgid "loader" msgstr "" #. (itstool) path: entry/screen #: book.translate.xml:372 #, no-wrap msgid "" "BTX loader 1.00 BTX version is 1.02\n" "Consoles: internal video/keyboard\n" "BIOS drive C: is disk0\n" "BIOS 639kB/2096064kB available memory\n" "\n" "FreeBSD/x86 bootstrap loader, Revision 1.1\n" "Console internal video/keyboard\n" "(root@snap.freebsd.org, Thu Jan 16 22:18:05 UTC 2014)\n" "Loading /boot/defaults/loader.conf\n" "/boot/kernel/kernel text=0xed9008 data=0x117d28+0x176650 syms=" "[0x8+0x137988+0x8+0x1515f8]" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:385 msgid "kernel" msgstr "" #. (itstool) path: entry/screen #: book.translate.xml:386 #, no-wrap msgid "" "Copyright (c) 1992-2013 The FreeBSD Project.\n" "Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994\n" " The Regents of the University of California. All rights reserved.\n" "FreeBSD is a registered trademark of The FreeBSD Foundation.\n" "FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014\n" " root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64\n" "FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:400 msgid "The BIOS" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:402 msgid "" "When the computer powers on, the processor's registers are set to some " "predefined values. One of the registers is the instruction " "pointer register, and its value after a power on is well defined: " "it is a 32-bit value of 0xfffffff0. The instruction " "pointer register (also known as the Program Counter) points to code to be " "executed by the processor. Another important register is the cr0 32-bit control register, and its value just after a reboot is " "0. One of cr0's bits, the PE " "(Protection Enabled) bit, indicates whether the processor is running in 32-" "bit protected mode or 16-bit real mode. Since this bit is cleared at boot " "time, the processor boots in 16-bit real mode. Real mode means, among other " "things, that linear and physical addresses are identical. The reason for the " "processor not to start immediately in 32-bit protected mode is backwards " "compatibility. In particular, the boot process relies on the services " "provided by the BIOS, and the BIOS " "itself works in legacy, 16-bit code." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:422 msgid "" "The value of 0xfffffff0 is slightly less than 4 GB, so " "unless the machine has 4 GB of physical memory, it cannot point to a valid " "memory address. The computer's hardware translates this address so that it " "points to a BIOS memory block." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:428 msgid "" "The BIOS (Basic Input Output System) is a chip on the " "motherboard that has a relatively small amount of read-only memory " "(ROM). This memory contains various low-level routines " "that are specific to the hardware supplied with the motherboard. The " "processor will first jump to the address 0xfffffff0, which really resides in " "the BIOS's memory. Usually this address contains a jump " "instruction to the BIOS's POST routines." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:438 msgid "" "The POST (Power On Self Test) is a set of routines " "including the memory check, system bus check, and other low-level " "initialization so the CPU can set up the computer " "properly. The important step of this stage is determining the boot device. " "Modern BIOS implementations permit the selection of a " "boot device, allowing booting from a floppy, CD-ROM, hard " "disk, or other devices." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:447 msgid "" "The very last thing in the POST is the INT 0x19 instruction. The INT 0x19 handler reads 512 " "bytes from the first sector of boot device into the memory at address " "0x7c00. The term first sector " "originates from hard drive architecture, where the magnetic plate is divided " "into a number of cylindrical tracks. Tracks are numbered, and every track is " "divided into a number (usually 64) of sectors. Track numbers start at 0, but " "sector numbers start from 1. Track 0 is the outermost on the magnetic plate, " "and sector 1, the first sector, has a special purpose. It is also called the " "MBR, or Master Boot Record. The remaining sectors on the " "first track are never used." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:462 msgid "" "This sector is our boot-sequence starting point. As we will see, this sector " "contains a copy of our boot0 program. A jump is made by " "the BIOS to address 0x7c00 so it " "starts executing." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:470 msgid "The Master Boot Record (boot0)" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:472 msgid "MBR" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:474 msgid "" "After control is received from the BIOS at memory address " "0x7c00, boot0 starts executing. It " "is the first piece of code under FreeBSD control. The task of " "boot0 is quite simple: scan the partition table and let " "the user choose which partition to boot from. The Partition Table is a " "special, standard data structure embedded in the MBR " "(hence embedded in boot0) describing the four standard " "PC partitions <_:footnote-1/>. boot0 " "resides in the filesystem as /boot/boot0. It is a small " "512-byte file, and it is exactly what FreeBSD's installation procedure wrote " "to the hard disk's MBR if you chose the " "bootmanager option at installation time. Indeed, " "boot0 is the MBR." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:494 msgid "" "As mentioned previously, the INT 0x19 instruction causes " "the INT 0x19 handler to load an MBR " "(boot0) into memory at address 0x7c00. The source file for boot0 can be found in " "sys/boot/i386/boot0/boot0.S - which is an awesome piece " "of code written by Robert Nordier." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:502 msgid "" "A special structure starting from offset 0x1be in the " "MBR is called the partition table. " "It has four records of 16 bytes each, called partition records, which represent how the hard disk is partitioned, or, in " "FreeBSD's terminology, sliced. One byte of those 16 says whether a partition " "(slice) is bootable or not. Exactly one record must have that flag set, " "otherwise boot0's code will refuse to proceed." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:512 msgid "A partition record has the following fields:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:516 msgid "the 1-byte filesystem type" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:520 msgid "the 1-byte bootable flag" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:524 msgid "the 6 byte descriptor in CHS format" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:528 msgid "the 8 byte descriptor in LBA format" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:532 msgid "" "A partition record descriptor contains information about where exactly the " "partition resides on the drive. Both descriptors, LBA and " "CHS, describe the same information, but in different ways:" " LBA (Logical Block Addressing) has the starting sector " "for the partition and the partition's length, while CHS " "(Cylinder Head Sector) has coordinates for the first and last sectors of the " "partition. The partition table ends with the special signature " "0xaa55." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:543 msgid "" "The MBR must fit into 512 bytes, a single disk sector. " "This program uses low-level tricks like taking advantage of " "the side effects of certain instructions and reusing register values from " "previous operations to make the most out of the fewest possible instructions." " Care must also be taken when handling the partition table, which is " "embedded in the MBR itself. For these reasons, be very " "careful when modifying boot0.S." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:553 msgid "" "Note that the boot0.S source file is assembled " "as is: instructions are translated one by one to binary, with " "no additional information (no ELF file format, for " "example). This kind of low-level control is achieved at link time through " "special control flags passed to the linker. For example, the text section of " "the program is set to be located at address 0x600. In " "practice this means that boot0 must be loaded to memory " "address 0x600 in order to function properly." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:564 msgid "" "It is worth looking at the Makefile for " "boot0 (sys/boot/i386/boot0/Makefile), as it defines some of the run-time behavior of boot0. For instance, if a terminal connected to the serial port (COM1) " "is used for I/O, the macro SIO must be defined (-" "DSIO). -DPXE enables boot through PXE by pressing F6. Additionally, the program defines " "a set of flags that allow further modification of its " "behavior. All of this is illustrated in the Makefile. " "For example, look at the linker directives which command the linker to start " "the text section at address 0x600, and to build the " "output file as is (strip out any file formatting):" msgstr "" #. (itstool) path: figure/title #: book.translate.xml:583 msgid "sys/boot/i386/boot0/Makefile" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:585 #, no-wrap msgid "" " BOOT_BOOT0_ORG?=0x600\n" " LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} \\\n" " -Wl,-N,-S,--oformat,binary" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:590 msgid "" "Let us now start our study of the MBR, or " "boot0, starting where execution begins." msgstr "" #. (itstool) path: note/para #: book.translate.xml:595 msgid "" "Some modifications have been made to some instructions in favor of better " "exposition. For example, some macros are expanded, and some macro tests are " "omitted when the result of the test is known. This applies to all of the " "code examples shown." msgstr "" #. (itstool) path: figure/title #: book.translate.xml:603 book.translate.xml:631 book.translate.xml:698 #: book.translate.xml:728 book.translate.xml:756 book.translate.xml:800 #: book.translate.xml:819 book.translate.xml:837 book.translate.xml:907 msgid "sys/boot/i386/boot0/boot0.S" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:605 #, no-wrap msgid "" "start:\n" " cld # String ops inc\n" " xorw %ax,%ax # Zero\n" " movw %ax,%es # Address\n" " movw %ax,%ds # data\n" " movw %ax,%ss # Set up\n" " movw 0x7c00,%sp # stack" msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:619 msgid "" "When in doubt, we refer the reader to the official Intel manuals, which " "describe the exact semantics for each instruction: ." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:614 msgid "" "This first block of code is the entry point of the program. It is where the " "BIOS transfers control. First, it makes sure that the " "string operations autoincrement its pointer operands (the cld instruction) <_:footnote-1/>. Then, as it makes no assumption about " "the state of the segment registers, it initializes them. Finally, it sets " "the stack pointer register (%sp) to address " "0x7c00, so we have a working stack." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:627 msgid "" "The next block is responsible for the relocation and subsequent jump to the " "relocated code." msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:633 #, no-wrap msgid "" " movw $0x7c00,%si # Source\n" " movw $0x600,%di # Destination\n" " movw $512,%cx # Word count\n" " rep # Relocate\n" " movsb # code\n" " movw %di,%bp # Address variables\n" " movb $16,%cl # Words to clear\n" " rep # Zero\n" " stosb # them\n" " incb -0xe(%di) # Set the S field to 1\n" " jmp main-0x7c00+0x600 # Jump to relocated code" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:646 msgid "" "Because boot0 is loaded by the BIOS " "to address 0x7C00, it copies itself to address " "0x600 and then transfers control there (recall that it " "was linked to execute at address 0x600). The source " "address, 0x7c00, is copied to register %si. The destination address, 0x600, to register " "%di. The number of bytes to copy, 512 " "(the program's size), is copied to register %cx. Next, " "the rep instruction repeats the instruction that follows, " "that is, movsb, the number of times dictated by the " "%cx register. The movsb instruction " "copies the byte pointed to by %si to the address pointed " "to by %di. This is repeated another 511 times. On each " "repetition, both the source and destination registers, %si and %di, are incremented by one. Thus, upon " "completion of the 512-byte copy, %di has the value " "0x600+512= 0x800, " "and %si has the value 0x7c00+512= 0x7e00; we have thus " "completed the code relocation." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:672 msgid "" "Next, the destination register %di is copied to " "%bp. %bp gets the value " "0x800. The value 16 is copied to " "%cl in preparation for a new string operation (like our " "previous movsb). Now, stosb is " "executed 16 times. This instruction copies a 0 value to " "the address pointed to by the destination register (%di, " "which is 0x800), and increments it. This is repeated " "another 15 times, so %di ends up with value " "0x810. Effectively, this clears the address range " "0x800-0x80f. This range is used as a " "(fake) partition table for writing the MBR back to disk. " "Finally, the sector field for the CHS addressing of this " "fake partition is given the value 1 and a jump is made to the main function " "from the relocated code. Note that until this jump to the relocated code, " "any reference to an absolute address was avoided." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:693 msgid "" "The following code block tests whether the drive number provided by the " "BIOS should be used, or the one stored in " "boot0." msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:700 #, no-wrap msgid "" "main:\n" " testb $SETDRV,-69(%bp) # Set drive number?\n" " jnz disable_update # Yes\n" " testb %dl,%dl # Drive number valid?\n" " js save_curdrive # Possibly (0x80 set)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:707 msgid "" "This code tests the SETDRV bit (0x20) " "in the flags variable. Recall that register " "%bp points to address location 0x800, " "so the test is done to the flags variable at address " "0x800-69= 0x7bb. " "This is an example of the type of modifications that can be done to " "boot0. The SETDRV flag is not set by " "default, but it can be set in the Makefile. When set, " "the drive number stored in the MBR is used instead of the " "one provided by the BIOS. We assume the defaults, and " "that the BIOS provided a valid drive number, so we jump " "to save_curdrive." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:723 msgid "" "The next block saves the drive number provided by the BIOS, and calls putn to print a new line on the " "screen." msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:730 #, no-wrap msgid "" "save_curdrive:\n" " movb %dl, (%bp) # Save drive number\n" " pushw %dx # Also in the stack\n" "#ifdef TEST /* test code, print internal bios drive */\n" " rolb $1, %dl\n" " movw $drive, %si\n" " call putkey\n" "#endif\n" " callw putn # Print a newline" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:741 msgid "" "Note that we assume TEST is not defined, so the " "conditional code in it is not assembled and will not appear in our " "executable boot0." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:745 msgid "" "Our next block implements the actual scanning of the partition table. It " "prints to the screen the partition type for each of the four entries in the " "partition table. It compares each type with a list of well-known operating " "system file systems. Examples of recognized partition types are " "NTFS (Windows, ID 0x7), ext2fs (Linux, ID 0x83), and, of course, ffs/ufs2 (FreeBSD, ID 0xa5). The implementation is " "fairly simple." msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:758 #, no-wrap msgid "" " movw $(partbl+0x4),%bx # Partition table (+4)\n" " xorw %dx,%dx # Item number\n" "\n" "read_entry:\n" " movb %ch,-0x4(%bx) # Zero active flag (ch == 0)\n" " btw %dx,_FLAGS(%bp) # Entry enabled?\n" " jnc next_entry # No\n" " movb (%bx),%al # Load type\n" " test %al, %al # skip empty partition\n" " jz next_entry\n" " movw $bootable_ids,%di # Lookup tables\n" " movb $(TLEN+1),%cl # Number of entries\n" " repne # Locate\n" " scasb # type\n" " addw $(TLEN-1), %di # Adjust\n" " movb (%di),%cl # Partition\n" " addw %cx,%di # description\n" " callw putx # Display it\n" "\n" "next_entry:\n" " incw %dx # Next item\n" " addb $0x10,%bl # Next entry\n" " jnc read_entry # Till done" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:783 msgid "" "It is important to note that the active flag for each entry is cleared, so " "after the scanning, no partition entry is active in our " "memory copy of boot0. Later, the active flag will be " "set for the selected partition. This ensures that only one active partition " "exists if the user chooses to write the changes back to disk." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:791 msgid "" "The next block tests for other drives. At startup, the BIOS writes the number of drives present in the computer to address " "0x475. If there are any other drives present, " "boot0 prints the current drive to screen. The user may " "command boot0 to scan partitions on another drive later." "" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:802 #, no-wrap msgid "" " popw %ax # Drive number\n" " subb $0x79,%al # Does next\n" " cmpb 0x475,%al # drive exist? (from BIOS?)\n" " jb print_drive # Yes\n" " decw %ax # Already drive 0?\n" " jz print_prompt # Yes" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:810 msgid "" "We make the assumption that a single drive is present, so the jump to " "print_drive is not performed. We also assume nothing " "strange happened, so we jump to print_prompt." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:815 msgid "" "This next block just prints out a prompt followed by the default option:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:821 #, no-wrap msgid "" "print_prompt:\n" " movw $prompt,%si # Display\n" " callw putstr # prompt\n" " movb _OPT(%bp),%dl # Display\n" " decw %si # default\n" " callw putkey # key\n" " jmp start_input # Skip beep" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:830 msgid "" "Finally, a jump is performed to start_input, where the " "BIOS services are used to start a timer and for reading " "user input from the keyboard; if the timer expires, the default option will " "be selected:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:839 #, no-wrap msgid "" "start_input:\n" " xorb %ah,%ah # BIOS: Get\n" " int $0x1a # system time\n" " movw %dx,%di # Ticks when\n" " addw _TICKS(%bp),%di # timeout\n" "read_key:\n" " movb $0x1,%ah # BIOS: Check\n" " int $0x16 # for keypress\n" " jnz got_key # Have input\n" " xorb %ah,%ah # BIOS: int 0x1a, 00\n" " int $0x1a # get system time\n" " cmpw %di,%dx # Timeout?\n" " jb read_key # No" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:854 msgid "" "An interrupt is requested with number 0x1a and argument " "0 in register %ah. The BIOS has a predefined set of services, requested by applications as " "software-generated interrupts through the int instruction " "and receiving arguments in registers (in this case, %ah). " "Here, particularly, we are requesting the number of clock ticks since last " "midnight; this value is computed by the BIOS through the " "RTC (Real Time Clock). This clock can be programmed to " "work at frequencies ranging from 2 Hz to 8192 Hz. The BIOS sets it to 18.2 Hz at startup. When the request is satisfied, a 32-" "bit result is returned by the BIOS in registers " "%cx and %dx (lower bytes in " "%dx). This result (the %dx part) is " "copied to register %di, and the value of the " "TICKS variable is added to %di. This " "variable resides in boot0 at offset _TICKS (a negative value) from register %bp (which, " "recall, points to 0x800). The default value of this " "variable is 0xb6 (182 in decimal). Now, the idea is that " "boot0 constantly requests the time from the " "BIOS, and when the value returned in register " "%dx is greater than the value stored in %di, the time is up and the default selection will be made. Since the " "RTC ticks 18.2 times per second, this condition will be met after 10 seconds " "(this default behavior can be changed in the Makefile). " "Until this time has passed, boot0 continually asks the " "BIOS for any user input; this is done through " "int 0x16, argument 1 in %ah." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:891 msgid "" "Whether a key was pressed or the time expired, subsequent code validates the " "selection. Based on the selection, the register %si is " "set to point to the appropriate partition entry in the partition table. This " "new selection overrides the previous default one. Indeed, it becomes the new " "default. Finally, the ACTIVE flag of the selected partition is set. If it " "was enabled at compile time, the in-memory version of boot0 with these modified values is written back to the MBR on disk. We leave the details of this implementation to the reader." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:903 msgid "" "We now end our study with the last code block from the boot0 program:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:909 #, no-wrap msgid "" " movw $0x7c00,%bx # Address for read\n" " movb $0x2,%ah # Read sector\n" " callw intx13 # from disk\n" " jc beep # If error\n" " cmpw $0xaa55,0x1fe(%bx) # Bootable?\n" " jne beep # No\n" " pushw %si # Save ptr to selected part.\n" " callw putn # Leave some space\n" " popw %si # Restore, next stage uses it\n" " jmp *%bx # Invoke bootstrap" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:921 msgid "" "Recall that %si points to the selected partition entry. " "This entry tells us where the partition begins on disk. We assume, of " "course, that the partition selected is actually a FreeBSD slice." msgstr "" #. (itstool) path: note/para #: book.translate.xml:927 msgid "" "From now on, we will favor the use of the technically more accurate term " "slice rather than partition." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:932 msgid "" "The transfer buffer is set to 0x7c00 (register " "%bx), and a read for the first sector of the FreeBSD " "slice is requested by calling intx13. We assume that " "everything went okay, so a jump to beep is not performed. " "In particular, the new sector read must end with the magic sequence " "0xaa55. Finally, the value at %si (the " "pointer to the selected partition table) is preserved for use by the next " "stage, and a jump is performed to address 0x7c00, where " "execution of our next stage (the just-read block) is started." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:946 msgid "boot1 Stage" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:948 msgid "So far we have gone through the following sequence:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:952 msgid "" "The BIOS did some early hardware initialization, " "including the POST. The MBR " "(boot0) was loaded from absolute disk sector one to " "address 0x7c00. Execution control was passed to that " "location." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:961 msgid "" "boot0 relocated itself to the location it was linked to " "execute (0x600), followed by a jump to continue execution " "at the appropriate place. Finally, boot0 loaded the " "first disk sector from the FreeBSD slice to address 0x7c00. Execution control was passed to that location." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:985 msgid "" "There is a file /boot/boot1, but it is not the written " "to the beginning of the FreeBSD slice. Instead, it is concatenated with " "boot2 to form boot, which " "is written to the beginning of the FreeBSD slice and " "read at boot time." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:971 msgid "" "boot1 is the next step in the boot-loading sequence. It " "is the first of three boot stages. Note that we have been dealing " "exclusively with disk sectors. Indeed, the BIOS loads the " "absolute first sector, while boot0 loads the first " "sector of the FreeBSD slice. Both loads are to address 0x7c00. We can conceptually think of these disk sectors as containing the " "files boot0 and boot1, " "respectively, but in reality this is not entirely true for boot1. Strictly speaking, unlike boot0, " "boot1 is not part of the boot blocks <_:footnote-1/>. " "Instead, a single, full-blown file, boot (/" "boot/boot), is what ultimately is written to disk. This file is a " "combination of boot1, boot2 and " "the Boot Extender (or BTX). This " "single file is greater in size than a single sector (greater than 512 bytes)." " Fortunately, boot1 occupies exactly the first 512 bytes of this single file, so when boot0 loads the first sector of the FreeBSD slice (512 bytes), it is " "actually loading boot1 and transferring control to it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1005 msgid "" "The main task of boot1 is to load the next boot stage. " "This next stage is somewhat more complex. It is composed of a server called " "the Boot Extender, or BTX, and a client, " "called boot2. As we will see, the last boot stage, " "loader, is also a client of the BTX " "server." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1013 msgid "" "Let us now look in detail at what exactly is done by boot1, starting like we did for boot0, at its entry " "point:" msgstr "" #. (itstool) path: figure/title #: book.translate.xml:1018 book.translate.xml:1029 book.translate.xml:1069 #: book.translate.xml:1114 book.translate.xml:1149 book.translate.xml:1176 #: book.translate.xml:1205 book.translate.xml:1311 msgid "sys/boot/i386/boot2/boot1.S" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1020 #, no-wrap msgid "start:\n" " jmp main" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1024 msgid "" "The entry point at start simply jumps past a special data " "area to the label main, which in turn looks like this:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1031 #, no-wrap msgid "" "main:\n" " cld # String ops inc\n" " xor %cx,%cx # Zero\n" " mov %cx,%es # Address\n" " mov %cx,%ds # data\n" " mov %cx,%ss # Set up\n" " mov $start,%sp # stack\n" " mov %sp,%si # Source\n" " mov $0x700,%di # Destination\n" " incb %ch # Word count\n" " rep # Copy\n" " movsw # code" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1045 msgid "" "Just like boot0, this code relocates boot1, this time to memory address 0x700. However, " "unlike boot0, it does not jump there. boot1 is linked to execute at address 0x7c00, " "effectively where it was loaded in the first place. The reason for this " "relocation will be discussed shortly." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1058 msgid "" "Actually we did pass a pointer to the slice entry in register %si. However, boot1 does not assume that it was " "loaded by boot0 (perhaps some other MBR loaded it, and did not pass this information), so it assumes " "nothing." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1054 msgid "" "Next comes a loop that looks for the FreeBSD slice. Although " "boot0 loaded boot1 from the " "FreeBSD slice, no information was passed to it about this <_:footnote-1/>, " "so boot1 must rescan the partition table to find where " "the FreeBSD slice starts. Therefore it rereads the MBR:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1071 #, no-wrap msgid "" " mov $part4,%si # Partition\n" " cmpb $0x80,%dl # Hard drive?\n" " jb main.4 # No\n" " movb $0x1,%dh # Block count\n" " callw nread # Read MBR" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1078 msgid "" "In the code above, register %dl maintains information " "about the boot device. This is passed on by the BIOS and " "preserved by the MBR. Numbers 0x80 and " "greater tells us that we are dealing with a hard drive, so a call is made to " "nread, where the MBR is read. " "Arguments to nread are passed through %si and %dh. The memory address at label " "part4 is copied to %si. This memory " "address holds a fake partition to be used by nread. The following is the data in the fake partition:" msgstr "" #. (itstool) path: figure/title #: book.translate.xml:1094 book.translate.xml:1387 book.translate.xml:1400 #: book.translate.xml:1432 book.translate.xml:1473 msgid "sys/boot/i386/boot2/Makefile" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1096 #, no-wrap msgid "" " part4:\n" " .byte 0x80, 0x00, 0x01, 0x00\n" " .byte 0xa5, 0xfe, 0xff, 0xff\n" " .byte 0x00, 0x00, 0x00, 0x00\n" " .byte 0x50, 0xc3, 0x00, 0x00" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1103 msgid "" "In particular, the LBA for this fake partition is " "hardcoded to zero. This is used as an argument to the BIOS for reading absolute sector one from the hard drive. Alternatively, " "CHS addressing could be used. In this case, the fake partition holds " "cylinder 0, head 0 and sector 1, which is equivalent to absolute sector one." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1110 msgid "Let us now proceed to take a look at nread:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1116 #, no-wrap msgid "" "nread:\n" " mov $0x8c00,%bx # Transfer buffer\n" " mov 0x8(%si),%ax # Get\n" " mov 0xa(%si),%cx # LBA\n" " push %cs # Read from\n" " callw xread.1 # disk\n" " jnc return # If success, return" msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1128 msgid "In the context of 16-bit real mode, a word is 2 bytes." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1125 msgid "" "Recall that %si points to the fake partition. The word <_:" "footnote-1/> at offset 0x8 is copied to register " "%ax and word at offset 0xa to " "%cx. They are interpreted by the BIOS " "as the lower 4-byte value denoting the LBA to be read (the upper four bytes " "are assumed to be zero). Register %bx holds the memory " "address where the MBR will be loaded. The instruction " "pushing %cs onto the stack is very interesting. In this " "context, it accomplishes nothing. However, as we will see shortly, " "boot2, in conjunction with the BTX " "server, also uses xread.1. This mechanism will be " "discussed in the next section." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1144 msgid "" "The code at xread.1 further calls the read function, which actually calls the BIOS asking " "for the disk sector:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1151 #, no-wrap msgid "" "xread.1:\n" " pushl $0x0 # absolute\n" " push %cx # block\n" " push %ax # number\n" " push %es # Address of\n" " push %bx # transfer buffer\n" " xor %ax,%ax # Number of\n" " movb %dh,%al # blocks to\n" " push %ax # transfer\n" " push $0x10 # Size of packet\n" " mov %sp,%bp # Packet pointer\n" " callw read # Read from disk\n" " lea 0x10(%bp),%sp # Clear stack\n" " lret # To far caller" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1167 msgid "" "Note the long return instruction at the end of this block. This instruction " "pops out the %cs register pushed by nread, and returns. Finally, nread also returns." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1172 msgid "" "With the MBR loaded to memory, the actual loop for " "searching the FreeBSD slice begins:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1178 #, no-wrap msgid "" " mov $0x1,%cx # Two passes\n" "main.1:\n" " mov $0x8dbe,%si # Partition table\n" " movb $0x1,%dh # Partition\n" "main.2:\n" " cmpb $0xa5,0x4(%si) # Our partition type?\n" " jne main.3 # No\n" " jcxz main.5 # If second pass\n" " testb $0x80,(%si) # Active?\n" " jnz main.5 # Yes\n" "main.3:\n" " add $0x10,%si # Next entry\n" " incb %dh # Partition\n" " cmpb $0x5,%dh # In table?\n" " jb main.2 # Yes\n" " dec %cx # Do two\n" " jcxz main.1 # passes" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1197 msgid "" "If a FreeBSD slice is identified, execution continues at main.5. Note that when a FreeBSD slice is found %si " "points to the appropriate entry in the partition table, and %dh holds the partition number. We assume that a FreeBSD slice is " "found, so we continue execution at main.5:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1207 #, no-wrap msgid "" "main.5:\n" " mov %dx,0x900 # Save args\n" " movb $0x10,%dh # Sector count\n" " callw nread # Read disk\n" " mov $0x9000,%bx # BTX\n" " mov 0xa(%bx),%si # Get BTX length and set\n" " add %bx,%si # %si to start of boot2.bin\n" " mov $0xc000,%di # Client page 2\n" " mov $0xa200,%cx # Byte\n" " sub %si,%cx # count\n" " rep # Relocate\n" " movsb # client" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1221 msgid "" "Recall that at this point, register %si points to the " "FreeBSD slice entry in the MBR partition table, so a call " "to nread will effectively read sectors at the beginning " "of this partition. The argument passed on register %dh " "tells nread to read 16 disk sectors. Recall that the " "first 512 bytes, or the first sector of the FreeBSD slice, coincides with " "the boot1 program. Also recall that the file written to " "the beginning of the FreeBSD slice is not /boot/boot1, " "but /boot/boot. Let us look at the size of these files " "in the filesystem:" msgstr "" #. (itstool) path: sect1/screen #. (itstool) id: book.translate.xml#boot-boot1-filesize #: book.translate.xml:1234 #, no-wrap msgid "" "-r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot0\n" "-r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot1\n" "-r--r--r-- 1 root wheel 7.5K Jan 8 00:15 /boot/boot2\n" "-r--r--r-- 1 root wheel 8.0K Jan 8 00:15 /boot/boot" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1239 msgid "" "Both boot0 and boot1 are 512 bytes " "each, so they fit exactly in one disk sector. " "boot2 is much bigger, holding both the BTX server and the boot2 client. Finally, a file " "called simply boot is 512 bytes larger than " "boot2. This file is a concatenation of boot1 and boot2. As already noted, boot0 is the file written to the absolute first disk sector (the " "MBR), and boot is the file written " "to the first sector of the FreeBSD slice; boot1 and " "boot2 are not written to disk. The " "command used to concatenate boot1 and boot2 into a single boot is merely cat " "boot1 boot2 > boot." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1266 msgid "512*16=8192 bytes, exactly the size of boot" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1258 msgid "" "So boot1 occupies exactly the first 512 bytes of " "boot and, because boot is written " "to the first sector of the FreeBSD slice, boot1 fits " "exactly in this first sector. Because nread reads the " "first 16 sectors of the FreeBSD slice, it effectively reads the entire " "boot file <_:footnote-1/>. We will see more details " "about how boot is formed from boot1 and boot2 in the next section." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1282 msgid "" "Historically known as disklabel. If you ever wondered where " "FreeBSD stored this information, it is in this region. See " "bsdlabel8" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1272 msgid "" "Recall that nread uses memory address 0x8c00 as the transfer buffer to hold the sectors read. This address is " "conveniently chosen. Indeed, because boot1 belongs to " "the first 512 bytes, it ends up in the address range 0x8c00-0x8dff. The 512 bytes that follows (range " "0x8e00-0x8fff) is used to store the " "bsdlabel <_:footnote-1/>." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1286 msgid "" "Starting at address 0x9000 is the beginning of the " "BTX server, and immediately following is the " "boot2 client. The BTX server acts as " "a kernel, and executes in protected mode in the most privileged level. In " "contrast, the BTX clients (boot2, " "for example), execute in user mode. We will see how this is accomplished in " "the next section. The code after the call to nread " "locates the beginning of boot2 in the memory buffer, " "and copies it to memory address 0xc000. This is because " "the BTX server arranges boot2 to " "execute in a segment starting at 0xa000. We explore this " "in detail in the following section." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1305 msgid "" "This is necessary for legacy reasons. Interested readers should see ." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1302 msgid "" "The last code block of boot1 enables access to memory " "above 1MB <_:footnote-1/> and concludes with a jump to the starting point of " "the BTX server:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1313 #, no-wrap msgid "" "seta20:\n" " cli # Disable interrupts\n" "seta20.1:\n" " dec %cx # Timeout?\n" " jz seta20.3 # Yes\n" "\n" " inb $0x64,%al # Get status\n" " testb $0x2,%al # Busy?\n" " jnz seta20.1 # Yes\n" " movb $0xd1,%al # Command: Write\n" " outb %al,$0x64 # output port\n" "seta20.2:\n" " inb $0x64,%al # Get status\n" " testb $0x2,%al # Busy?\n" " jnz seta20.2 # Yes\n" " movb $0xdf,%al # Enable\n" " outb %al,$0x60 # A20\n" "seta20.3:\n" " sti # Enable interrupts\n" " jmp 0x9010 # Start BTX" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1335 msgid "Note that right before the jump, interrupts are enabled." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:1340 msgid "The BTX Server" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1342 msgid "" "Next in our boot sequence is the BTX Server. Let us " "quickly remember how we got here:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1348 msgid "" "The BIOS loads the absolute sector one (the MBR, or boot0), to address 0x7c00 and jumps there." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1355 msgid "" "boot0 relocates itself to 0x600, the " "address it was linked to execute, and jumps over there. It then reads the " "first sector of the FreeBSD slice (which consists of boot1) into address 0x7c00 and jumps over there." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1364 msgid "" "boot1 loads the first 16 sectors of the FreeBSD slice " "into address 0x8c00. This 16 sectors, or 8192 bytes, is " "the whole file boot. The file is a concatenation of " "boot1 and boot2. boot2, in turn, contains the BTX server and the " "boot2 client. Finally, a jump is made to address " "0x9010, the entry point of the BTX " "server." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1377 msgid "" "Before studying the BTX Server in detail, let us further " "review how the single, all-in-one boot file is created. " "The way boot is built is defined in its " "Makefile (/usr/src/sys/boot/i386/boot2/" "Makefile). Let us look at the rule that creates the " "boot file:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1389 #, no-wrap msgid " boot: boot1 boot2\n" " cat boot1 boot2 > boot" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1393 msgid "" "This tells us that boot1 and boot2 " "are needed, and the rule simply concatenates them to produce a single file " "called boot. The rules for creating boot1 are also quite simple:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1402 #, no-wrap msgid "" " boot1: boot1.out\n" " objcopy -S -O binary boot1.out boot1\n" "\n" " boot1.out: boot1.o\n" " ld -e start -Ttext 0x7c00 -o boot1.out boot1.o" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1409 msgid "" "To apply the rule for creating boot1, boot1." "out must be resolved. This, in turn, depends on the existence of " "boot1.o. This last file is simply the result of " "assembling our familiar boot1.S, without linking. Now, " "the rule for creating boot1.out is applied. This tells " "us that boot1.o should be linked with start as its entry point, and starting at address 0x7c00. Finally, boot1 is created from " "boot1.out applying the appropriate rule. This rule is " "the objcopy command applied to boot1.out. Note the flags passed to objcopy: -" "S tells it to strip all relocation and symbolic information; " "-O binary indicates the output format, that is, a simple, " "unformatted binary file." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1428 msgid "" "Having boot1, let us take a look at how " "boot2 is constructed:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1434 #, no-wrap msgid "" " boot2: boot2.ld\n" " @set -- `ls -l boot2.ld`; x=$$((7680-$$5)); \\\n" " echo \"$$x bytes available\"; test $$x -ge 0\n" " dd if=boot2.ld of=boot2 obs=7680 conv=osync\n" "\n" " boot2.ld: boot2.ldr boot2.bin ../btx/btx/btx\n" " btxld -v -E 0x2000 -f bin -b ../btx/btx/btx -l boot2.ldr \\\n" " -o boot2.ld -P 1 boot2.bin\n" "\n" " boot2.ldr:\n" " dd if=/dev/zero of=boot2.ldr bs=512 count=1\n" "\n" " boot2.bin: boot2.out\n" " objcopy -S -O binary boot2.out boot2.bin\n" "\n" " boot2.out: ../btx/lib/crt0.o boot2.o sio.o\n" " ld -Ttext 0x2000 -o boot2.out\n" "\n" " boot2.o: boot2.s\n" " ${CC} ${ACFLAGS} -c boot2.s\n" "\n" " boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c\n" " ${CC} ${CFLAGS} -S -o boot2.s.tmp ${.CURDIR}/boot2.c\n" " sed -e '/align/d' -e '/nop/d' \"MISSING\" boot2.s.tmp > boot2.s\n" " rm -f boot2.s.tmp\n" "\n" " boot2.h: boot1.out\n" " ${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \\\n" " { x = $$1 - ORG1; \\\n" " printf(\"#define XREADORG %#x\\n\", REL1 + x) }' \\\n" " ORG1=`printf \"%d\" ${ORG1}` \\\n" " REL1=`printf \"%d\" ${REL1}` > ${.TARGET}" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1468 msgid "" "The mechanism for building boot2 is far more elaborate. " "Let us point out the most relevant facts. The dependency list is as follows:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1475 #, no-wrap msgid "" " boot2: boot2.ld\n" " boot2.ld: boot2.ldr boot2.bin ${BTXDIR}/btx/btx\n" " boot2.bin: boot2.out\n" " boot2.out: ${BTXDIR}/lib/crt0.o boot2.o sio.o\n" " boot2.o: boot2.s\n" " boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c\n" " boot2.h: boot1.out" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1484 msgid "" "Note that initially there is no header file boot2.h, " "but its creation depends on boot1.out, which we already " "have. The rule for its creation is a bit terse, but the important thing is " "that the output, boot2.h, is something like this:" msgstr "" #. (itstool) path: figure/title #: book.translate.xml:1492 msgid "sys/boot/i386/boot2/boot2.h" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1494 #, no-wrap msgid "\n" " #define XREADORG 0x725" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1498 msgid "" "Recall that boot1 was relocated (i.e., copied from " "0x7c00 to 0x700). This relocation will " "now make sense, because as we will see, the BTX server " "reclaims some memory, including the space where boot1 " "was originally loaded. However, the BTX server needs " "access to boot1's xread function; " "this function, according to the output of boot2.h, is " "at location 0x725. Indeed, the BTX " "server uses the xread function from boot1's relocated code. This function is now accessible from within the " "boot2 client." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1515 msgid "" "We next build boot2.s from files boot2.h, boot2.c and /usr/src/sys/boot/" "common/ufsread.c. The rule for this is to compile the code in " "boot2.c (which includes boot2.h " "and ufsread.c) into assembly code. Having " "boot2.s, the next rule assembles boot2.s, creating the object file boot2.o. The next " "rule directs the linker to link various files (crt0.o, " "boot2.o and sio.o). Note that the " "output file, boot2.out, is linked to execute at address " "0x2000. Recall that boot2 will be " "executed in user mode, within a special user segment set up by the " "BTX server. This segment starts at 0xa000. Also, remember that the boot2 portion of " "boot was copied to address 0xc000, " "that is, offset 0x2000 from the start of the user " "segment, so boot2 will work properly when we transfer " "control to it. Next, boot2.bin is created from " "boot2.out by stripping its symbols and format " "information; boot2.bin is a raw binary. Now, note that " "a file boot2.ldr is created as a 512-byte file full of " "zeros. This space is reserved for the bsdlabel." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1544 msgid "" "Now that we have files boot1, boot2.bin and boot2.ldr, only the BTX server is missing before creating the all-in-one boot file. The BTX server is located in /" "usr/src/sys/boot/i386/btx/btx; it has its own Makefile with its own set of rules for building. The important thing to " "notice is that it is also compiled as a raw binary, and " "that it is linked to execute at address 0x9000. The " "details can be found in /usr/src/sys/boot/i386/btx/btx/Makefile." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1558 msgid "" "Having the files that comprise the boot program, the " "final step is to merge them. This is done by a special " "program called btxld (source located in /usr/" "src/usr.sbin/btxld). Some arguments to this program include the " "name of the output file (boot), its entry point " "(0x2000) and its file format (raw binary). The various " "files are finally merged by this utility into the file boot, which consists of boot1, boot2, the bsdlabel and the BTX " "server. This file, which takes exactly 16 sectors, or 8192 bytes, is what is " "actually written to the beginning of the FreeBSD slice during instalation. " "Let us now proceed to study the BTX server program." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1577 msgid "" "The BTX server prepares a simple environment and switches " "from 16-bit real mode to 32-bit protected mode, right before passing control " "to the client. This includes initializing and updating the following data " "structures:" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:1583 msgid "virtual v86 mode" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1586 msgid "" "Modifies the Interrupt Vector Table (IVT). The " "IVT provides exception and interrupt handlers for Real-" "Mode code." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1593 msgid "" "The Interrupt Descriptor Table (IDT) is created. Entries " "are provided for processor exceptions, hardware interrupts, two system calls " "and V86 interface. The IDT provides exception and interrupt handlers for " "Protected-Mode code." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1601 msgid "" "A Task-State Segment (TSS) is created. This is necessary " "because the processor works in the least privileged " "level when executing the client (boot2), but in the " "most privileged level when executing the BTX server." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:1615 msgid "" "Real-mode code and data are necessary when switching back to real mode from " "protected mode, as suggested by the Intel manuals." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:1610 msgid "" "The GDT (Global Descriptor Table) is set up. Entries " "(descriptors) are provided for supervisor code and data, user code and data, " "and real-mode code and data. <_:footnote-1/>" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1621 msgid "" "Let us now start studying the actual implementation. Recall that " "boot1 made a jump to address 0x9010, " "the BTX server's entry point. Before studying program " "execution there, note that the BTX server has a special " "header at address range 0x9000-0x900f, right before its " "entry point. This header is defined as follows:" msgstr "" #. (itstool) path: figure/title #: book.translate.xml:1630 book.translate.xml:1661 book.translate.xml:1690 #: book.translate.xml:1731 book.translate.xml:1759 book.translate.xml:1830 #: book.translate.xml:1855 book.translate.xml:1904 msgid "sys/boot/i386/btx/btx/btx.S" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1632 #, no-wrap msgid "" "start: # Start of code\n" "/*\n" " * BTX header.\n" " */\n" "btx_hdr: .byte 0xeb # Machine ID\n" " .byte 0xe # Header size\n" " .ascii \"BTX\" # Magic\n" " .byte 0x1 # Major version\n" " .byte 0x2 # Minor version\n" " .byte BTX_FLAGS # Flags\n" " .word PAG_CNT-MEM_ORG>>0xc # Paging control\n" " .word break-start # Text size\n" " .long 0x0 # Entry address" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1647 msgid "" "Note the first two bytes are 0xeb and 0xe. In the IA-32 architecture, these two bytes are interpreted as a " "relative jump past the header into the entry point, so in theory, " "boot1 could jump here (address 0x9000) instead of address 0x9010. Note that the last " "field in the BTX header is a pointer to the client's " "(boot2) entry point. This field is patched at link time." "" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1657 msgid "" "Immediately following the header is the BTX server's " "entry point:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1663 #, no-wrap msgid "" "/*\n" " * Initialization routine.\n" " */\n" "init: cli # Disable interrupts\n" " xor %ax,%ax # Zero/segment\n" " mov %ax,%ss # Set up\n" " mov $0x1800,%sp # stack\n" " mov %ax,%es # Address\n" " mov %ax,%ds # data\n" " pushl $0x2 # Clear\n" " popfl # flags" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1676 msgid "" "This code disables interrupts, sets up a working stack (starting at address " "0x1800) and clears the flags in the EFLAGS register. Note " "that the popfl instruction pops out a doubleword (4 " "bytes) from the stack and places it in the EFLAGS register. Because the " "value actually popped is 2, the EFLAGS register is " "effectively cleared (IA-32 requires that bit 2 of the EFLAGS register always " "be 1)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1685 msgid "" "Our next code block clears (sets to 0) the memory range " "0x5e00-0x8fff. This range is where the various data " "structures will be created:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1692 #, no-wrap msgid "" "/*\n" " * Initialize memory.\n" " */\n" " mov $0x5e00,%di # Memory to initialize\n" " mov $(0x9000-0x5e00)/2,%cx # Words to zero\n" " rep # Zero-fill\n" " stosw # memory" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1701 msgid "" "Recall that boot1 was originally loaded to address " "0x7c00, so, with this memory initialization, that copy " "effectively dissapeared. However, also recall that boot1 was relocated to 0x700, so that copy is still in memory, and the BTX server " "will make use of it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1709 msgid "" "Next, the real-mode IVT (Interrupt Vector Table is " "updated. The IVT is an array of segment/offset pairs for " "exception and interrupt handlers. The BIOS normally maps " "hardware interrupts to interrupt vectors 0x8 to " "0xf and 0x70 to 0x77 but, as will be seen, the 8259A Programmable Interrupt Controller, " "the chip controlling the actual mapping of hardware interrupts to interrupt " "vectors, is programmed to remap these interrupt vectors from 0x8-" "0xf to 0x20-0x27 and from 0x70-0x77 to 0x28-0x2f. Thus, interrupt handlers are " "provided for interrupt vectors 0x20-0x2f. The reason the " "BIOS-provided handlers are not used directly is because " "they work in 16-bit real mode, but not 32-bit protected mode. Processor mode " "will be switched to 32-bit protected mode shortly. However, the " "BTX server sets up a mechanism to effectively use the " "handlers provided by the BIOS:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1733 #, no-wrap msgid "" "/*\n" " * Update real mode IDT for reflecting hardware interrupts.\n" " */\n" " mov $intr20,%bx # Address first handler\n" " mov $0x10,%cx # Number of handlers\n" " mov $0x20*4,%di # First real mode IDT entry\n" "init.0: mov %bx,(%di) # Store IP\n" " inc %di # Address next\n" " inc %di # entry\n" " stosw # Store CS\n" " add $4,%bx # Next handler\n" " loop init.0 # Next IRQ" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1747 msgid "" "The next block creates the IDT (Interrupt Descriptor " "Table). The IDT is analogous, in protected mode, to the " "IVT in real mode. That is, the IDT " "describes the various exception and interrupt handlers used when the " "processor is executing in protected mode. In essence, it also consists of an " "array of segment/offset pairs, although the structure is somewhat more " "complex, because segments in protected mode are different than in real mode, " "and various protection mechanisms apply:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1761 #, no-wrap msgid "" "/*\n" " * Create IDT.\n" " */\n" " mov $0x5e00,%di # IDT's address\n" " mov $idtctl,%si # Control string\n" "init.1: lodsb # Get entry\n" " cbw # count\n" " xchg %ax,%cx # as word\n" " jcxz init.4 # If done\n" " lodsb # Get segment\n" " xchg %ax,%dx # P:DPL:type\n" " lodsw # Get control\n" " xchg %ax,%bx # set\n" " lodsw # Get handler offset\n" " mov $SEL_SCODE,%dh # Segment selector\n" "init.2: shr %bx # Handle this int?\n" " jnc init.3 # No\n" " mov %ax,(%di) # Set handler offset\n" " mov %dh,0x2(%di) # and selector\n" " mov %dl,0x5(%di) # Set P:DPL:type\n" " add $0x4,%ax # Next handler\n" "init.3: lea 0x8(%di),%di # Next entry\n" " loop init.2 # Till set done\n" " jmp init.1 # Continue" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1787 msgid "" "Each entry in the IDT is 8 bytes long. Besides the " "segment/offset information, they also describe the segment type, privilege " "level, and whether the segment is present in memory or not. The construction " "is such that interrupt vectors from 0 to 0xf (exceptions) are handled by function intx00; " "vector 0x10 (also an exception) is handled by " "intx10; hardware interrupts, which are later configured " "to start at interrupt vector 0x20 all the way to " "interrupt vector 0x2f, are handled by function " "intx20. Lastly, interrupt vector 0x30, " "which is used for system calls, is handled by intx30, and " "vectors 0x31 and 0x32 are handled by " "intx31. It must be noted that only descriptors for " "interrupt vectors 0x30, 0x31 and " "0x32 are given privilege level 3, the same privilege " "level as the boot2 client, which means the client can " "execute a software-generated interrupt to this vectors through the " "int instruction without failing (this is the way " "boot2 use the services provided by the BTX server). Also, note that only software-" "generated interrupts are protected from code executing in lesser privilege " "levels. Hardware-generated interrupts and processor-generated exceptions are " "always handled adequately, regardless of the actual " "privileges involved." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1817 msgid "" "The next step is to initialize the TSS (Task-State " "Segment). The TSS is a hardware feature that helps the " "operating system or executive software implement multitasking functionality " "through process abstraction. The IA-32 architecture demands the creation and " "use of at least one TSS if " "multitasking facilities are used or different privilege levels are defined. " "Because the boot2 client is executed in privilege level " "3, but the BTX server does in privilege level 0, a " "TSS must be defined:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1832 #, no-wrap msgid "" "/*\n" " * Initialize TSS.\n" " */\n" "init.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0\n" " movb $SEL_SDATA,TSS_SS0(%di) # Set SS0\n" " movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1840 msgid "" "Note that a value is given for the Privilege Level 0 stack pointer and stack " "segment in the TSS. This is needed because, if an " "interrupt or exception is received while executing boot2 in Privilege Level 3, a change to Privilege Level 0 is " "automatically performed by the processor, so a new working stack is needed. " "Finally, the I/O Map Base Address field of the TSS is " "given a value, which is a 16-bit offset from the beginning of the " "TSS to the I/O Permission Bitmap and the Interrupt " "Redirection Bitmap." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1850 msgid "" "After the IDT and TSS are created, the " "processor is ready to switch to protected mode. This is done in the next " "block:" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1857 #, no-wrap msgid "" "/*\n" " * Bring up the system.\n" " */\n" " mov $0x2820,%bx # Set protected mode\n" " callw setpic # IRQ offsets\n" " lidt idtdesc # Set IDT\n" " lgdt gdtdesc # Set GDT\n" " mov %cr0,%eax # Switch to protected\n" " inc %ax # mode\n" " mov %eax,%cr0 #\n" " ljmp $SEL_SCODE,$init.8 # To 32-bit code\n" " .code32\n" "init.8: xorl %ecx,%ecx # Zero\n" " movb $SEL_SDATA,%cl # To 32-bit\n" " movw %cx,%ss # stack" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1874 msgid "" "First, a call is made to setpic to program the 8259A " "PIC (Programmable Interrupt Controller). This chip is " "connected to multiple hardware interrupt sources. Upon receiving an " "interrupt from a device, it signals the processor with the appropriate " "interrupt vector. This can be customized so that specific interrupts are " "associated with specific interrupt vectors, as explained before. Next, the " "IDTR (Interrupt Descriptor Table Register) and " "GDTR (Global Descriptor Table Register) are loaded with " "the instructions lidt and lgdt, " "respectively. These registers are loaded with the base address and limit " "address for the IDT and GDT. The " "following three instructions set the Protection Enable (PE) bit of the " "%cr0 register. This effectively switches the processor to " "32-bit protected mode. Next, a long jump is made to init.8 using segment selector SEL_SCODE, which selects the Supervisor Code " "Segment. The processor is effectively executing in CPL 0, the most " "privileged level, after this jump. Finally, the Supervisor Data Segment is " "selected for the stack by assigning the segment selector SEL_SDATA to the " "%ss register. This data segment also has a privilege " "level of 0." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1897 msgid "" "Our last code block is responsible for loading the TR " "(Task Register) with the segment selector for the TSS we " "created earlier, and setting the User Mode environment before passing " "execution control to the boot2 client." msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:1906 #, no-wrap msgid "" "/*\n" " * Launch user task.\n" " */\n" " movb $SEL_TSS,%cl # Set task\n" " ltr %cx # register\n" " movl $0xa000,%edx # User base address\n" " movzwl %ss:BDA_MEM,%eax # Get free memory\n" " shll $0xa,%eax # To bytes\n" " subl $ARGSPACE,%eax # Less arg space\n" " subl %edx,%eax # Less base\n" " movb $SEL_UDATA,%cl # User data selector\n" " pushl %ecx # Set SS\n" " pushl %eax # Set ESP\n" " push $0x202 # Set flags (IF set)\n" " push $SEL_UCODE # Set CS\n" " pushl btx_hdr+0xc # Set EIP\n" " pushl %ecx # Set GS\n" " pushl %ecx # Set FS\n" " pushl %ecx # Set DS\n" " pushl %ecx # Set ES\n" " pushl %edx # Set EAX\n" " movb $0x7,%cl # Set remaining\n" "init.9: push $0x0 # general\n" " loop init.9 # registers\n" " popa # and initialize\n" " popl %es # Initialize\n" " popl %ds # user\n" " popl %fs # segment\n" " popl %gs # registers\n" " iret # To user mode" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1938 msgid "" "Note that the client's environment include a stack segment selector and " "stack pointer (registers %ss and %esp)." " Indeed, once the TR is loaded with the appropriate stack " "segment selector (instruction ltr), the stack pointer is " "calculated and pushed onto the stack along with the stack's segment selector." " Next, the value 0x202 is pushed onto the stack; it is " "the value that the EFLAGS will get when control is passed to the client. " "Also, the User Mode code segment selector and the client's entry point are " "pushed. Recall that this entry point is patched in the BTX header at link time. Finally, segment selectors (stored in register " "%ecx) for the segment registers %gs, %fs, %ds " "and %es are pushed onto the stack, along with the value at " "%edx (0xa000). Keep in mind the " "various values that have been pushed onto the stack (they will be popped out " "shortly). Next, values for the remaining general purpose registers are also " "pushed onto the stack (note the loop that pushes the " "value 0 seven times). Now, values will be started to be " "popped out of the stack. First, the popa instruction pops " "out of the stack the latest seven values pushed. They are stored in the " "general purpose registers in order %edi, %esi, %ebp, %ebx, %edx, " "%ecx, %eax. Then, the various segment selectors pushed are popped " "into the various segment registers. Five values still remain on the stack. " "They are popped when the iret instruction is executed. " "This instruction first pops the value that was pushed from the BTX header. This value is a pointer to boot2's " "entry point. It is placed in the register %eip, the " "instruction pointer register. Next, the segment selector for the User Code " "Segment is popped and copied to register %cs. Remember " "that this segment's privilege level is 3, the least privileged level. This " "means that we must provide values for the stack of this privilege level. " "This is why the processor, besides further popping the value for the EFLAGS " "register, does two more pops out of the stack. These values go to the stack " "pointer (%esp) and the stack segment (%ss). Now, execution continues at boot0's entry " "point." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1983 msgid "" "It is important to note how the User Code Segment is defined. This segment's " "base address is set to 0xa000. This " "means that code memory addresses are relative to " "address 0xa000; if code being executed is fetched from address " "0x2000, the actual memory addressed " "is 0xa000+0x2000=0xc000." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:1994 msgid "boot2 Stage" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:1996 msgid "" "boot2 defines an important structure, struct " "bootinfo. This structure is initialized by boot2 and passed to the loader, and then further to the kernel. Some " "nodes of this structures are set by boot2, the rest by " "the loader. This structure, among other information, contains the kernel " "filename, BIOS harddisk geometry, BIOS " "drive number for boot device, physical memory available, envp pointer etc. The definition for it is:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2006 #, no-wrap msgid "" "/usr/include/machine/bootinfo.h:\n" "struct bootinfo {\n" " u_int32_t bi_version;\n" " u_int32_t bi_kernelname; /* represents a char * */\n" " u_int32_t bi_nfs_diskless; /* struct nfs_diskless * */\n" " /* End of fields that are always present. */\n" "#define bi_endcommon bi_n_bios_used\n" " u_int32_t bi_n_bios_used;\n" " u_int32_t bi_bios_geom[N_BIOS_GEOM];\n" " u_int32_t bi_size;\n" " u_int8_t bi_memsizes_valid;\n" " u_int8_t bi_bios_dev; /* bootdev BIOS unit number */\n" " u_int8_t bi_pad[2];\n" " u_int32_t bi_basemem;\n" " u_int32_t bi_extmem;\n" " u_int32_t bi_symtab; /* struct symtab * */\n" " u_int32_t bi_esymtab; /* struct symtab * */\n" " /* Items below only from advanced bootloader */\n" " u_int32_t bi_kernend; /* end of kernel space */\n" " u_int32_t bi_envp; /* environment */\n" " u_int32_t bi_modulep; /* preloaded modules */\n" "};" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2029 msgid "" "boot2 enters into an infinite loop waiting for user " "input, then calls load(). If the user does not press " "anything, the loop breaks by a timeout, so load() will " "load the default file (/boot/loader). Functions " "ino_t lookup(char *filename) and int " "xfsread(ino_t inode, void *buf, size_t nbyte) are used to read " "the content of a file into memory. /boot/loader is an " "ELF binary, but where the ELF header " "is prepended with a.out's struct exec structure. load() scans the loader's ELF " "header, loading the content of /boot/loader into " "memory, and passing the execution to the loader's entry:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2044 #, no-wrap msgid "" "sys/boot/i386/boot2/boot2.c:\n" " __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),\n" " MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),\n" " 0, 0, 0, VTOP(&bootinfo));" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2051 msgid "loader Stage" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2053 msgid "" "loader is a BTX client as well." " I will not describe it here in detail, there is a comprehensive manpage " "written by Mike Smith, loader8. The underlying " "mechanisms and BTX were discussed above." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2058 msgid "" "The main task for the loader is to boot the kernel. When the kernel is " "loaded into memory, it is being called by the loader:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2062 #, no-wrap msgid "" "sys/boot/common/boot.c:\n" " /* Call the exec handler from the loader matching the kernel */\n" " module_formats[km->m_loader]->l_exec(km);" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2068 msgid "Kernel Initialization" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2070 msgid "" "Let us take a look at the command that links the kernel. This will help " "identify the exact location where the loader passes execution to the kernel. " "This location is the kernel's actual entry point." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2075 #, no-wrap msgid "" "sys/conf/Makefile.i386:\n" "ld -elf -Bdynamic -T /usr/src/sys/conf/ldscript.i386 -export-dynamic \\\n" "-dynamic-linker /red/herring -o kernel -X locore.o \\\n" "<lots of kernel .o files>" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2080 msgid "ELF" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2081 msgid "" "A few interesting things can be seen here. First, the kernel is an ELF " "dynamically linked binary, but the dynamic linker for kernel is /" "red/herring, which is definitely a bogus file. Second, taking a " "look at the file sys/conf/ldscript.i386 gives an idea " "about what ld options are used when compiling a " "kernel. Reading through the first few lines, the string" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2090 #, no-wrap msgid "sys/conf/ldscript.i386:\n" "ENTRY(btext)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2093 msgid "" "says that a kernel's entry point is the symbol `btext'. This symbol is " "defined in locore.s:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2096 #, no-wrap msgid "" "sys/i386/i386/locore.s:\n" " .text\n" "/**********************************************************************\n" " *\n" " * This is where the bootblocks start us, set the ball rolling...\n" " *\n" " */\n" "NON_GPROF_ENTRY(btext)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2105 msgid "" "First, the register EFLAGS is set to a predefined value of 0x00000002. Then " "all the segment registers are initialized:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2109 #, no-wrap msgid "" "sys/i386/i386/locore.s:\n" "/* Don't trust what the BIOS gives for eflags. */\n" " pushl $PSL_KERNEL\n" " popfl\n" "\n" "/*\n" " * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap\n" " * to set %cs, %ds, %es and %ss.\n" " */\n" " mov %ds, %ax\n" " mov %ax, %fs\n" " mov %ax, %gs" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2122 msgid "" "btext calls the routines recover_bootinfo(), " "identify_cpu(), create_pagetables(), which are also defined in locore.s. Here is " "a description of what they do:" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2133 msgid "recover_bootinfo" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2134 msgid "" "This routine parses the parameters to the kernel passed from the bootstrap. " "The kernel may have been booted in 3 ways: by the loader, described above, " "by the old disk boot blocks, or by the old diskless boot procedure. This " "function determines the booting method, and stores the struct " "bootinfo structure into the kernel memory." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2144 msgid "identify_cpu" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2145 msgid "" "This functions tries to find out what CPU it is running on, storing the " "value found in a variable _cpu." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2151 msgid "create_pagetables" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2152 msgid "" "This function allocates and fills out a Page Table Directory at the top of " "the kernel memory area." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2159 msgid "The next steps are enabling VME, if the CPU supports it:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2162 #, no-wrap msgid "" " testl $CPUID_VME, R(_cpu_feature)\n" " jz 1f\n" " movl %cr4, %eax\n" " orl $CR4_VME, %eax\n" " movl %eax, %cr4" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2168 msgid "Then, enabling paging:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2170 #, no-wrap msgid "" "/* Now enable paging */\n" " movl R(_IdlePTD), %eax\n" " movl %eax,%cr3 /* load ptd addr into mmu */\n" " movl %cr0,%eax /* get control word */\n" " orl $CR0_PE|CR0_PG,%eax /* enable paging */\n" " movl %eax,%cr0 /* and let's page NOW! */" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2177 msgid "" "The next three lines of code are because the paging was set, so the jump is " "needed to continue the execution in virtualized address space:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2181 #, no-wrap msgid "" " pushl $begin /* jump to high virtualized address */\n" " ret\n" "\n" "/* now running relocated at KERNBASE where the system is linked to run */\n" "begin:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2187 msgid "" "The function init386() is called with a pointer to the " "first free physical page, after that mi_startup(). " "init386 is an architecture dependent initialization " "function, and mi_startup() is an architecture " "independent one (the 'mi_' prefix stands for Machine Independent). The " "kernel never returns from mi_startup(), and by calling " "it, the kernel finishes booting:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:2196 #, no-wrap msgid "" "sys/i386/i386/locore.s:\n" " movl physfree, %esi\n" " pushl %esi /* value of first for init386(first) */\n" " call _init386 /* wire 386 chip for unix operation */\n" " call _mi_startup /* autoconfiguration, mountroot etc */\n" " hlt /* never returns to here */" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:2204 msgid "init386()" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2206 msgid "" "init386() is defined in sys/i386/i386/machdep." "c and performs low-level initialization specific to the i386 chip." " The switch to protected mode was performed by the loader. The loader has " "created the very first task, in which the kernel continues to operate. " "Before looking at the code, consider the tasks the processor must complete " "to initialize protected mode execution:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2217 msgid "" "Initialize the kernel tunable parameters, passed from the bootstrapping " "program." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2222 msgid "Prepare the GDT." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2226 msgid "Prepare the IDT." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2230 msgid "Initialize the system console." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2234 msgid "Initialize the DDB, if it is compiled into kernel." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2239 msgid "Initialize the TSS." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2243 msgid "Prepare the LDT." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2247 msgid "Set up proc0's pcb." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:2251 msgid "parameters" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2252 msgid "" "init386() initializes the tunable parameters passed " "from bootstrap by setting the environment pointer (envp) and calling " "init_param1(). The envp pointer has been passed from " "loader in the bootinfo structure:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2258 #, no-wrap msgid "" "sys/i386/i386/machdep.c:\n" " kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;\n" "\n" " /* Init basic tunables, hz etc */\n" " init_param1();" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2264 msgid "" "init_param1() is defined in sys/kern/" "subr_param.c. That file has a number of sysctls, and two " "functions, init_param1() and init_param2(), that are called from init386():" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2271 #, no-wrap msgid "" "sys/kern/subr_param.c:\n" " hz = HZ;\n" " TUNABLE_INT_FETCH(\"kern.hz\", &hz);" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2275 msgid "" "TUNABLE_<typename>_FETCH is used to fetch the value from the " "environment:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2278 #, no-wrap msgid "" "/usr/src/sys/sys/kernel.h:\n" "#define TUNABLE_INT_FETCH(path, var) getenv_int((path), (var))" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2281 msgid "" "Sysctl kern.hz is the system clock tick. Additionally, " "these sysctls are set by init_param1(): kern." "maxswzone, kern.maxbcache, kern.maxtsiz, kern.dfldsiz, kern.maxdsiz, kern." "dflssiz, kern.maxssiz, kern.sgrowsiz." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:2287 msgid "Global Descriptors Table (GDT)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2291 msgid "" "Then init386() prepares the Global Descriptors Table " "(GDT). Every task on an x86 is running in its own virtual address space, and " "this space is addressed by a segment:offset pair. Say, for instance, the " "current instruction to be executed by the processor lies at CS:EIP, then the " "linear virtual address for that instruction would be the virtual " "address of code segment CS + EIP. For convenience, segments begin at " "virtual address 0 and end at a 4Gb boundary. Therefore, the instruction's " "linear virtual address for this example would just be the value of EIP. " "Segment registers such as CS, DS etc are the selectors, i.e., indexes, into " "GDT (to be more precise, an index is not a selector itself, but the INDEX " "field of a selector). FreeBSD's GDT holds descriptors for 15 selectors per " "CPU:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2307 #, no-wrap msgid "" "sys/i386/i386/machdep.c:\n" "union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */\n" "\n" "sys/i386/include/segments.h:\n" "/*\n" " * Entries in the Global Descriptor Table (GDT)\n" " */\n" "#define GNULL_SEL 0 /* Null Descriptor */\n" "#define GCODE_SEL 1 /* Kernel Code Descriptor */\n" "#define GDATA_SEL 2 /* Kernel Data Descriptor */\n" "#define GPRIV_SEL 3 /* SMP Per-Processor Private Data */\n" "#define GPROC0_SEL 4 /* Task state process slot zero and up */\n" "#define GLDT_SEL 5 /* LDT - eventually one per process */\n" "#define GUSERLDT_SEL 6 /* User LDT */\n" "#define GTGATE_SEL 7 /* Process task switch gate */\n" "#define GBIOSLOWMEM_SEL 8 /* BIOS low memory access (must be entry 8) */\n" "#define GPANIC_SEL 9 /* Task state to consider panic from */\n" "#define GBIOSCODE32_SEL 10 /* BIOS interface (32bit Code) */\n" "#define GBIOSCODE16_SEL 11 /* BIOS interface (16bit Code) */\n" "#define GBIOSDATA_SEL 12 /* BIOS interface (Data) */\n" "#define GBIOSUTIL_SEL 13 /* BIOS interface (Utility) */\n" "#define GBIOSARGS_SEL 14 /* BIOS interface (Arguments) */" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2330 msgid "" "Note that those #defines are not selectors themselves, but just a field " "INDEX of a selector, so they are exactly the indices of the GDT. for " "example, an actual selector for the kernel code (GCODE_SEL) has the value " "0x08." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:2335 msgid "Interrupt Descriptor Table (IDT)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2337 msgid "" "The next step is to initialize the Interrupt Descriptor Table (IDT). This " "table is referenced by the processor when a software or hardware interrupt " "occurs. For example, to make a system call, user application issues the " "INT 0x80 instruction. This is a software interrupt, so " "the processor's hardware looks up a record with index 0x80 in the IDT. This " "record points to the routine that handles this interrupt, in this particular " "case, this will be the kernel's syscall gate. The IDT may have a maximum of " "256 (0x100) records. The kernel allocates NIDT records for the IDT, where " "NIDT is the maximum (256):" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2349 #, no-wrap msgid "" "sys/i386/i386/machdep.c:\n" "static struct gate_descriptor idt0[NIDT];\n" "struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2353 msgid "" "For each interrupt, an appropriate handler is set. The syscall gate for " "INT 0x80 is set as well:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2357 #, no-wrap msgid "" "sys/i386/i386/machdep.c:\n" " setidt(0x80, &IDTVEC(int0x80_syscall),\n" " SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2361 msgid "" "So when a userland application issues the INT 0x80 " "instruction, control will transfer to the function " "_Xint0x80_syscall, which is in the kernel code segment " "and will be executed with supervisor privileges." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2367 msgid "Console and DDB are then initialized:" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:2368 msgid "DDB" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2370 #, no-wrap msgid "" "sys/i386/i386/machdep.c:\n" " cninit();\n" "/* skipped */\n" "#ifdef DDB\n" " kdb_init();\n" " if (boothowto & RB_KDB)\n" " Debugger(\"Boot flags requested debugger\");\n" "#endif" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2379 msgid "" "The Task State Segment is another x86 protected mode structure, the TSS is " "used by the hardware to store task information when a task switch occurs." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2383 msgid "" "The Local Descriptors Table is used to reference userland code and data. " "Several selectors are defined to point to the LDT, they are the system call " "gates and the user code and data selectors:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2388 #, no-wrap msgid "" "/usr/include/machine/segments.h:\n" "#define LSYS5CALLS_SEL 0 /* forced by intel BCS */\n" "#define LSYS5SIGR_SEL 1\n" "#define L43BSDCALLS_SEL 2 /* notyet */\n" "#define LUCODE_SEL 3\n" "#define LSOL26CALLS_SEL 4 /* Solaris >= 2.6 system call gate */\n" "#define LUDATA_SEL 5\n" "/* separate stack, es,fs,gs sels ? */\n" "/* #define LPOSIXCALLS_SEL 5*/ /* notyet */\n" "#define LBSDICALLS_SEL 16 /* BSDI system call gate */\n" "#define NLDT (LBSDICALLS_SEL + 1)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2400 msgid "" "Next, proc0's Process Control Block (struct pcb) " "structure is initialized. proc0 is a struct proc " "structure that describes a kernel process. It is always present while the " "kernel is running, therefore it is declared as global:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2406 #, no-wrap msgid "sys/kern/kern_init.c:\n" " struct proc proc0;" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2409 msgid "" "The structure struct pcb is a part of a proc structure. " "It is defined in /usr/include/machine/pcb.h and has a " "process's information specific to the i386 architecture, such as registers " "values." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:2417 msgid "mi_startup()" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2419 msgid "" "This function performs a bubble sort of all the system initialization " "objects and then calls the entry of each object one by one:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2423 #, no-wrap msgid "" "sys/kern/init_main.c:\n" " for (sipp = sysinit; *sipp; sipp++) {\n" "\n" " /* ... skipped ... */\n" "\n" " /* Call function */\n" " (*((*sipp)->func))((*sipp)->udata);\n" " /* ... skipped ... */\n" " }" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2433 msgid "" "Although the sysinit framework is described in the Developers' Handbook, I will discuss the internals of it." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:2436 msgid "sysinit objects" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2437 msgid "" "Every system initialization object (sysinit object) is created by calling a " "SYSINIT() macro. Let us take as example an announce " "sysinit object. This object prints the copyright message:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2442 #, no-wrap msgid "" "sys/kern/init_main.c:\n" "static void\n" "print_caddr_t(void *data __unused)\n" "{\n" " printf(\"%s\", (char *)data);\n" "}\n" "SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, " "copyright)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2450 msgid "" "The subsystem ID for this object is SI_SUB_COPYRIGHT (0x0800001), which " "comes right after the SI_SUB_CONSOLE (0x0800000). So, the copyright message " "will be printed out first, just after the console initialization." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2455 msgid "" "Let us take a look at what exactly the macro SYSINIT() " "does. It expands to a C_SYSINIT() macro. The " "C_SYSINIT() macro then expands to a static " "struct sysinit structure declaration with another " "DATA_SET macro call:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2462 #, no-wrap msgid "" "/usr/include/sys/kernel.h:\n" " #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \\\n" " static struct sysinit uniquifier ## _sys_init = { \\ subsystem, \\\n" " order, \\ func, \\ ident \\ }; \\ DATA_SET(sysinit_set,uniquifier ##\n" " _sys_init);\n" "\n" "#define SYSINIT(uniquifier, subsystem, order, func, ident) \\\n" " C_SYSINIT(uniquifier, subsystem, order, \\\n" " (sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)ident)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2472 msgid "" "The DATA_SET() macro expands to a MAKE_SET(), and that macro is the point where all the sysinit magic is hidden:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2476 #, no-wrap msgid "" "/usr/include/linker_set.h:\n" "#define MAKE_SET(set, sym) \\\n" " static void const * const __set_##set##_sym_##sym = &sym; \\\n" " __asm(\".section .set.\" #set \",\\\"aw\\\"\"); \\\n" " __asm(\".long \" #sym); \\\n" " __asm(\".previous\")\n" "#endif\n" "#define TEXT_SET(set, sym) MAKE_SET(set, sym)\n" "#define DATA_SET(set, sym) MAKE_SET(set, sym)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2486 msgid "In our case, the following declaration will occur:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2488 #, no-wrap msgid "" "static struct sysinit announce_sys_init = {\n" " SI_SUB_COPYRIGHT,\n" " SI_ORDER_FIRST,\n" " (sysinit_cfunc_t)(sysinit_nfunc_t) print_caddr_t,\n" " (void *) copyright\n" "};\n" "\n" "static void const *const __set_sysinit_set_sym_announce_sys_init =\n" " &announce_sys_init;\n" "__asm(\".section .set.sysinit_set\" \",\\\"aw\\\"\");\n" "__asm(\".long \" \"announce_sys_init\");\n" "__asm(\".previous\");" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2501 msgid "" "The first __asm instruction will create an ELF section " "within the kernel's executable. This will happen at kernel link time. The " "section will have the name .set.sysinit_set. The content " "of this section is one 32-bit value, the address of announce_sys_init " "structure, and that is what the second __asm is. The " "third __asm instruction marks the end of a section. If a " "directive with the same section name occurred before, the content, i.e., the " "32-bit value, will be appended to the existing section, so forming an array " "of 32-bit pointers." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2514 msgid "" "Running objdump on a kernel binary, you may " "notice the presence of such small sections:" msgstr "" #. (itstool) path: sect2/screen #: book.translate.xml:2518 #, no-wrap msgid "" "% objdump -h /kernel\n" " 7 .set.cons_set 00000014 c03164c0 c03164c0 002154c0 2**2\n" " CONTENTS, ALLOC, LOAD, DATA\n" " 8 .set.kbddriver_set 00000010 c03164d4 c03164d4 002154d4 2**2\n" " CONTENTS, ALLOC, LOAD, DATA\n" " 9 .set.scrndr_set 00000024 c03164e4 c03164e4 002154e4 2**2\n" " CONTENTS, ALLOC, LOAD, DATA\n" " 10 .set.scterm_set 0000000c c0316508 c0316508 00215508 2**2\n" " CONTENTS, ALLOC, LOAD, DATA\n" " 11 .set.sysctl_set 0000097c c0316514 c0316514 00215514 2**2\n" " CONTENTS, ALLOC, LOAD, DATA\n" " 12 .set.sysinit_set 00000664 c0316e90 c0316e90 00215e90 2**2\n" " CONTENTS, ALLOC, LOAD, DATA" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2532 msgid "" "This screen dump shows that the size of .set.sysinit_set section is 0x664 " "bytes, so 0x664/sizeof(void *) sysinit objects are " "compiled into the kernel. The other sections such as .set." "sysctl_set represent other linker sets." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2538 msgid "" "By defining a variable of type struct linker_set the " "content of .set.sysinit_set section will be " "collected into that variable:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2543 #, no-wrap msgid "" "sys/kern/init_main.c:\n" " extern struct linker_set sysinit_set; /* XXX */" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2546 msgid "The struct linker_set is defined as follows:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2549 #, no-wrap msgid "" "/usr/include/linker_set.h:\n" " struct linker_set {\n" " int ls_length;\n" " void *ls_items[1]; /* really ls_length of them, trailing NULL */\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2555 msgid "" "The first node will be equal to the number of a sysinit objects, and the " "second node will be a NULL-terminated array of pointers to them." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2559 msgid "" "Returning to the mi_startup() discussion, it is must be " "clear now, how the sysinit objects are being organized. The " "mi_startup() function sorts them and calls each. The " "very last object is the system scheduler:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2565 #, no-wrap msgid "" "/usr/include/sys/kernel.h:\n" "enum sysinit_sub_id {\n" " SI_SUB_DUMMY = 0x0000000, /* not executed; for linker*/\n" " SI_SUB_DONE = 0x0000001, /* processed*/\n" " SI_SUB_CONSOLE = 0x0800000, /* console*/\n" " SI_SUB_COPYRIGHT = 0x0800001, /* first use of console*/\n" "...\n" " SI_SUB_RUN_SCHEDULER = 0xfffffff /* scheduler: no return*/\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2575 msgid "" "The system scheduler sysinit object is defined in the file sys/vm/" "vm_glue.c, and the entry point for that object is " "scheduler(). That function is actually an infinite " "loop, and it represents a process with PID 0, the swapper process. The proc0 " "structure, mentioned before, is used to describe it." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2582 msgid "" "The first user process, called init, is created by the " "sysinit object init:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2586 #, no-wrap msgid "" "sys/kern/init_main.c:\n" "static void\n" "create_init(const void *udata __unused)\n" "{\n" " int error;\n" " int s;\n" "\n" " s = splhigh();\n" " error = fork1(&proc0, RFFDG | RFPROC, &initproc);\n" " if (error)\n" " panic(\"cannot fork init: %d\\n\", error);\n" " initproc->p_flag |= P_INMEM | P_SYSTEM;\n" " cpu_set_fork_handler(initproc, start_init, NULL);\n" " remrunqueue(initproc);\n" " splx(s);\n" "}\n" "SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:2604 msgid "" "The create_init() allocates a new process by calling " "fork1(), but does not mark it runnable. When this new " "process is scheduled for execution by the scheduler, the " "start_init() will be called. That function is defined " "in init_main.c. It tries to load and exec the " "init binary, probing /sbin/init " "first, then /sbin/oinit, /sbin/init.bak, and finally /stand/sysinstall:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:2616 #, no-wrap msgid "" "sys/kern/init_main.c:\n" "static char init_path[MAXPATHLEN] =\n" "#ifdef INIT_PATH\n" " __XSTRING(INIT_PATH);\n" "#else\n" " \"/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall\";\n" "#endif" msgstr "" #. (itstool) path: chapter/title #: book.translate.xml:2635 msgid "Locking Notes" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2637 msgid "SMP Next Generation Project" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:2638 msgid "" "This chapter is maintained by the FreeBSD SMP Next Generation " "Project." msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2641 msgid "locking" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2642 msgid "multi-processing" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2643 msgid "mutexes" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2644 msgid "lockmgr" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2645 msgid "atomic operations" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:2646 msgid "" "This document outlines the locking used in the FreeBSD kernel to permit " "effective multi-processing within the kernel. Locking can be achieved via " "several means. Data structures can be protected by mutexes or " "lockmgr9 locks. A few variables are protected simply by " "always using atomic operations to access them." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2654 msgid "Mutexes" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2656 msgid "" "A mutex is simply a lock used to guarantee mutual exclusion. Specifically, a " "mutex may only be owned by one entity at a time. If another entity wishes to " "obtain a mutex that is already owned, it must wait until the mutex is " "released. In the FreeBSD kernel, mutexes are owned by processes." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2662 msgid "" "Mutexes may be recursively acquired, but they are intended to be held for a " "short period of time. Specifically, one may not sleep while holding a mutex. " "If you need to hold a lock across a sleep, use a " "lockmgr9 lock." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2667 msgid "Each mutex has several properties of interest:" msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2671 book.translate.xml:2758 book.translate.xml:2918 msgid "Variable Name" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2673 msgid "The name of the struct mtx variable in the kernel source." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2679 book.translate.xml:2759 msgid "Logical Name" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2681 msgid "" "The name of the mutex assigned to it by mtx_init. This " "name is displayed in KTR trace messages and witness errors and warnings and " "is used to distinguish mutexes in the witness code." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2689 book.translate.xml:2760 msgid "Type" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2691 msgid "" "The type of the mutex in terms of the MTX_* flags. The " "meaning for each flag is related to its meaning as documented in " "mutex9." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2698 book.translate.xml:2851 msgid "MTX_DEF" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2700 msgid "A sleep mutex" msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:2705 msgid "MTX_SPIN" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2707 msgid "A spin mutex" msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:2712 msgid "MTX_RECURSE" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2714 msgid "This mutex is allowed to recurse." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2722 book.translate.xml:2761 book.translate.xml:2919 msgid "Protectees" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2724 msgid "" "A list of data structures or data structure members that this entry protects." " For data structure members, the name will be in the form of structure name.member name." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: row/entry #: book.translate.xml:2732 book.translate.xml:2762 msgid "Dependent Functions" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2734 msgid "Functions that can only be called if this mutex is held." msgstr "" #. (itstool) path: table/title #: book.translate.xml:2741 msgid "Mutex List" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2743 msgid "locks sched_lock" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2746 msgid "locks vm86pcb_lock" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2749 msgid "locks Giant" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2752 msgid "locks callout_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2769 msgid "sched_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2770 msgid "sched lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2771 book.translate.xml:2878 msgid "MTX_SPIN | MTX_RECURSE" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2775 msgid "" "_gmonparam, cnt.v_swtch, " "cp_time, curpriority, mtx.mtx_blocked, mtx.mtx_contested, proc.p_procq, proc.p_slpq, proc.p_sflag, proc.p_stat, proc.p_estcpu, proc.p_cpticks proc.p_pctcpu, proc.p_wchan, proc.p_wmesg, proc.p_swtime, proc.p_slptime, proc.p_runtime, proc.p_uu, proc.p_su, " "proc.p_iu, proc." "p_uticks, proc.p_sticks, proc.p_iticks, proc.p_oncpu, proc.p_lastcpu, proc.p_rqindex, proc.p_heldmtx, proc.p_blocked, proc.p_mtxname, proc.p_contested, proc.p_priority, proc.p_usrpri, proc.p_nativepri, proc.p_nice, proc.p_rtprio, pscnt, slpque, itqueuebits, " "itqueues, rtqueuebits, " "rtqueues, queuebits, queues, idqueuebits, idqueues, " "switchtime, switchticks" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2825 msgid "" "setrunqueue, remrunqueue, " "mi_switch, chooseproc, " "schedclock, resetpriority, " "updatepri, maybe_resched, " "cpu_switch, cpu_throw, " "need_resched, resched_wanted, " "clear_resched, aston, " "astoff, astpending, " "calcru, proc_compare" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2849 msgid "vm86pcb_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2850 msgid "vm86pcb lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2854 msgid "vm86pcb" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2857 msgid "vm86_bioscall" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2864 msgid "Giant" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2865 msgid "Giant" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2866 msgid "MTX_DEF | MTX_RECURSE" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2870 msgid "nearly everything" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2871 msgid "lots" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2876 msgid "callout_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2877 msgid "callout lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2882 msgid "" "callfree, callwheel, " "nextsoftcheck, proc.p_itcallout, proc.p_slpcallout, softticks, " "ticks" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2900 msgid "Shared Exclusive Locks" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2902 msgid "" "These locks provide basic reader-writer type functionality and may be held " "by a sleeping process. Currently they are backed by " "lockmgr9." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2905 msgid "locks shared exclusive" msgstr "" #. (itstool) path: table/title #: book.translate.xml:2909 msgid "Shared Exclusive Lock List" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2910 msgid "locks allproc_lock" msgstr "" #. (itstool) path: table/indexterm #: book.translate.xml:2912 msgid "locks proctree_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2924 msgid "allproc_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2925 msgid "" "allproc zombproc pidhashtbl proc.p_list proc.p_hash nextpid" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2935 msgid "proctree_lock" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:2936 msgid "" "proc.p_children proc.p_sibling" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2947 msgid "Atomically Protected Variables" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2949 msgid "atomically protected variables" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:2951 msgid "" "An atomically protected variable is a special variable that is not protected " "by an explicit lock. Instead, all data accesses to the variables use special " "atomic operations as described in atomic9. Very few variables " "are treated this way, although other synchronization primitives such as " "mutexes are implemented with atomically protected variables." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2961 msgid "" "mtx.mtx_lock" msgstr "" #. (itstool) path: chapter/title #: book.translate.xml:2974 msgid "Kernel Objects" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2976 msgid "Kernel Objects" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2977 msgid "Object-Oriented" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:2978 msgid "binary compatibility" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:2979 msgid "" "Kernel Objects, or Kobj provides an object-oriented C " "programming system for the kernel. As such the data being operated on " "carries the description of how to operate on it. This allows operations to " "be added and removed from an interface at run time and without breaking " "binary compatibility." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:2987 book.translate.xml:4094 msgid "Terminology" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2989 msgid "object" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2990 msgid "method" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2991 msgid "class" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:2992 msgid "interface" msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:2996 msgid "Object" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:2997 msgid "A set of data - data structure - data allocation." msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:3002 msgid "Method" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3004 msgid "An operation - function." msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:3008 msgid "Class" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3010 msgid "One or more methods." msgstr "" #. (itstool) path: varlistentry/term #. (itstool) path: sect2/title #: book.translate.xml:3014 book.translate.xml:4155 msgid "Interface" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3016 msgid "A standard set of one or more methods." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:3023 msgid "Kobj Operation" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:3025 msgid "" "Kobj works by generating descriptions of methods. Each description holds a " "unique id as well as a default function. The description's address is used " "to uniquely identify the method within a class' method table." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:3030 msgid "" "A class is built by creating a method table associating one or more " "functions with method descriptions. Before use the class is compiled. The " "compilation allocates a cache and associates it with the class. A unique id " "is assigned to each method description within the method table of the class " "if not already done so by another referencing class compilation. For every " "method to be used a function is generated by script to qualify arguments and " "automatically reference the method description for a lookup. The generated " "function looks up the method by using the unique id associated with the " "method description as a hash into the cache associated with the object's " "class. If the method is not cached the generated function proceeds to use " "the class' table to find the method. If the method is found then the " "associated function within the class is used; otherwise, the default " "function associated with the method description is used." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:3047 msgid "These indirections can be visualized as the following:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:3050 #, no-wrap msgid "object->cache<->class" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:3055 msgid "Using Kobj" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3058 msgid "Structures" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3060 #, no-wrap msgid "struct kobj_method" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3064 msgid "Functions" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3066 #, no-wrap msgid "" "void kobj_class_compile(kobj_class_t cls);\n" "void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);\n" "void kobj_class_free(kobj_class_t cls);\n" "kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags);\n" "void kobj_init(kobj_t obj, kobj_class_t cls);\n" "void kobj_delete(kobj_t obj, struct malloc_type *mtype);" msgstr "" #. (itstool) path: sect2/title #. (itstool) path: sect3/title #: book.translate.xml:3075 book.translate.xml:4164 msgid "Macros" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3077 #, no-wrap msgid "" "KOBJ_CLASS_FIELDS\n" "KOBJ_FIELDS\n" "DEFINE_CLASS(name, methods, size)\n" "KOBJMETHOD(NAME, FUNC)" msgstr "" #. (itstool) path: sect2/title #. (itstool) path: sect3/title #: book.translate.xml:3084 book.translate.xml:4158 msgid "Headers" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3086 #, no-wrap msgid "<sys/param.h>\n" "<sys/kobj.h>" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3091 msgid "Creating an Interface Template" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3093 msgid "Kernel Objects interface" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3096 msgid "" "The first step in using Kobj is to create an Interface. Creating the " "interface involves creating a template that the script src/sys/" "kern/makeobjops.pl can use to generate the header and code for " "the method declarations and method lookup functions." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3103 msgid "" "Within this template the following keywords are used: #include, INTERFACE, CODE, " "METHOD, STATICMETHOD, and " "DEFAULT." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3109 msgid "" "The #include statement and what follows it is copied " "verbatim to the head of the generated code file." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3113 book.translate.xml:3122 book.translate.xml:3130 #: book.translate.xml:3143 book.translate.xml:3159 book.translate.xml:3196 msgid "For example:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3115 #, no-wrap msgid "#include <sys/foo.h>" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3117 msgid "" "The INTERFACE keyword is used to define the interface " "name. This name is concatenated with each method name as [interface " "name]_[method name]. Its syntax is INTERFACE [interface name];." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3124 #, no-wrap msgid "INTERFACE foo;" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3126 msgid "" "The CODE keyword copies its arguments verbatim into the " "code file. Its syntax is CODE { [whatever] };" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3132 #, no-wrap msgid "" "CODE {\n" " struct foo * foo_alloc_null(struct bar *)\n" " {\n" " return NULL;\n" "}\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3139 msgid "" "The METHOD keyword describes a method. Its syntax is " "METHOD [return type] [method name] { [object [, arguments]] };" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3145 #, no-wrap msgid "METHOD int bar {\n" " struct object *;\n" " struct foo *;\n" " struct bar;\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3151 msgid "" "The DEFAULT keyword may follow the METHOD keyword. It extends the METHOD key word to " "include the default function for method. The extended syntax is " "METHOD [return type] [method name] { [object; [other arguments]] " "}DEFAULT [default function];" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3161 #, no-wrap msgid "" "METHOD int bar {\n" " struct object *;\n" " struct foo *;\n" " int bar;\n" "} DEFAULT foo_hack;" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3167 msgid "" "The STATICMETHOD keyword is used like the " "METHOD keyword except the kobj data is not at the head of " "the object structure so casting to kobj_t would be incorrect. Instead " "STATICMETHOD relies on the Kobj data being referenced as " "'ops'. This is also useful for calling methods directly out of a class's " "method table." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3174 msgid "Other complete examples:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3176 #, no-wrap msgid "src/sys/kern/bus_if.m\n" "src/sys/kern/device_if.m" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3182 msgid "Creating a Class" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3184 msgid "Kernel Objects class" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3187 msgid "" "The second step in using Kobj is to create a class. A class consists of a " "name, a table of methods, and the size of objects if Kobj's object handling " "facilities are used. To create the class use the macro " "DEFINE_CLASS(). To create the method table create an " "array of kobj_method_t terminated by a NULL entry. Each non-NULL entry may " "be created using the macro KOBJMETHOD()." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3198 #, no-wrap msgid "" "DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));\n" "\n" "kobj_method_t foomethods[] = {\n" " KOBJMETHOD(bar_doo, foo_doo),\n" " KOBJMETHOD(bar_foo, foo_foo),\n" " { NULL, NULL}\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3206 msgid "" "The class must be compiled. Depending on the state of the " "system at the time that the class is to be initialized a statically " "allocated cache, ops table have to be used. This can be " "accomplished by declaring a struct kobj_ops and using kobj_class_compile_static(); " "otherwise, kobj_class_compile() should be used." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3216 msgid "Creating an Object" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3218 msgid "Kernel Objects object" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3221 msgid "" "The third step in using Kobj involves how to define the object. Kobj object " "creation routines assume that Kobj data is at the head of an object. If this " "in not appropriate you will have to allocate the object yourself and then " "use kobj_init() on the Kobj portion of it; otherwise, " "you may use kobj_create() to allocate and initialize " "the Kobj portion of the object automatically. kobj_init() may also be used to change the class that an object uses." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3231 msgid "" "To integrate Kobj into the object you should use the macro KOBJ_FIELDS." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3234 msgid "For example" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3236 #, no-wrap msgid "struct foo_data {\n" " KOBJ_FIELDS;\n" " foo_foo;\n" " foo_bar;\n" "};" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3244 msgid "Calling Methods" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3246 msgid "" "The last step in using Kobj is to simply use the generated functions to use " "the desired method within the object's class. This is as simple as using the " "interface name and the method name with a few modifications. The interface " "name should be concatenated with the method name using a '_' between them, " "all in upper case." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3253 msgid "" "For example, if the interface name was foo and the method was bar then the " "call would be:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3256 #, no-wrap msgid "[return value = ] FOO_BAR(object [, other parameters]);" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3261 msgid "Cleaning Up" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3263 msgid "" "When an object allocated through kobj_create() is no " "longer needed kobj_delete() may be called on it, and " "when a class is no longer being used kobj_class_free() " "may be called on it." msgstr "" #. (itstool) path: info/title #: book.translate.xml:3280 msgid "The Jail Subsystem" msgstr "" #. (itstool) path: affiliation/address #: book.translate.xml:3288 #, no-wrap msgid "\n" " evms@cs.bu.edu\n" " " msgstr "" #. (itstool) path: info/author #: book.translate.xml:3282 msgid "" " Evan Sarmiento <_:address-1/> " msgstr "" #. (itstool) path: info/copyright #: book.translate.xml:3293 msgid "" "2001 Evan Sarmiento" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:3299 msgid "security" msgstr "" #. (itstool) path: chapter/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:3300 book.translate.xml:15439 msgid "Jail" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:3301 msgid "root" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:3303 msgid "" "On most UNIX systems, " "root has omnipotent power. This promotes insecurity. If " "an attacker gained root on a system, he would have every " "function at his fingertips. In FreeBSD there are sysctls which dilute the " "power of root, in order to minimize the damage caused by " "an attacker. Specifically, one of these functions is called secure " "levels. Similarly, another function which is present from FreeBSD " "4.0 and onward, is a utility called jail8. Jail chroots an environment and sets certain restrictions on " "processes which are forked within the jail. For " "example, a jailed process cannot affect processes outside the " "jail, utilize certain system calls, or inflict " "any damage on the host environment." msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:3318 msgid "" "Jail is becoming the new security model. People " "are running potentially vulnerable servers such as Apache, BIND, and sendmail within jails, so that if an attacker gains root within the jail, it is only an " "annoyance, and not a devastation. This article mainly focuses on the " "internals (source code) of jail. For information " "on how to set up a jail see the handbook entry on jails." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:3331 msgid "Architecture" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:3333 msgid "" "Jail consists of two realms: the userland " "program, jail8, and the code implemented within the kernel: the " "jail2 system call and associated restrictions. I will be discussing " "the userland program and then how jail is " "implemented within the kernel." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3341 msgid "Userland Code" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3343 msgid "Jail Userland Program" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3346 msgid "" "The source for the userland jail is located in " "/usr/src/usr.sbin/jail, consisting of one file, " "jail.c. The program takes these arguments: the path of " "the jail, hostname, IP address, and the command " "to be executed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:3354 msgid "Data Structures" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3356 msgid "" "In jail.c, the first thing I would note is the " "declaration of an important structure struct jail j; " "which was included from /usr/include/sys/jail.h." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3361 msgid "The definition of the jail structure is:" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3364 #, no-wrap msgid "" "/usr/include/sys/jail.h:\n" "\n" "struct jail {\n" " u_int32_t version;\n" " char *path;\n" " char *hostname;\n" " u_int32_t ip_number;\n" "};" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3373 msgid "" "As you can see, there is an entry for each of the arguments passed to the " "jail8 program, and indeed, they are set during its execution." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3377 #, no-wrap msgid "" "/usr/src/usr.sbin/jail/jail.c\n" "char path[PATH_MAX];\n" "...\n" "if (realpath(argv[0], path) == NULL)\n" " err(1, \"realpath: %s\", argv[0]);\n" "if (chdir(path) != 0)\n" " err(1, \"chdir: %s\", path);\n" "memset(&j, 0, sizeof(j));\n" "j.version = 0;\n" "j.path = path;\n" "j.hostname = argv[1];" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:3391 msgid "Networking" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3393 msgid "" "One of the arguments passed to the jail8 program is an IP " "address with which the jail can be accessed over " "the network. jail8 translates the IP address given into host byte " "order and then stores it in j (the jail structure)." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3400 #, no-wrap msgid "" "/usr/src/usr.sbin/jail/jail.c:\n" "struct in_addr in;\n" "...\n" "if (inet_aton(argv[2], &in) == 0)\n" " errx(1, \"Could not make sense of ip-number: %s\", argv[2]);\n" "j.ip_number = ntohl(in.s_addr);" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3407 msgid "" "The inet_aton3 function \"interprets the specified character " "string as an Internet address, placing the address into the structure " "provided.\" The ip_number member in the jail structure is set only when the IP address placed onto the " "in structure by inet_aton3 is translated into " "host byte order by ntohl3." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:3418 msgid "Jailing the Process" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3420 msgid "" "Finally, the userland program jails the process. Jail now becomes an imprisoned process itself and then executes the " "command given using execv3." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3425 #, no-wrap msgid "" "/usr/src/usr.sbin/jail/jail.c\n" "i = jail(&j);\n" "...\n" "if (execv(argv[3], argv + 3) != 0)\n" " err(1, \"execv: %s\", argv[3]);" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3431 msgid "" "As you can see, the jail() function is called, and its " "argument is the jail structure which has been filled with " "the arguments given to the program. Finally, the program you specify is " "executed. I will now discuss how jail is " "implemented within the kernel." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3441 msgid "Kernel Space" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3443 msgid "Jail Kernel Architecture" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3446 msgid "" "We will now be looking at the file /usr/src/sys/kern/kern_jail.c. This is the file where the jail2 system call, " "appropriate sysctls, and networking functions are defined." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:3452 msgid "Sysctls" msgstr "" #. (itstool) path: sect3/indexterm #: book.translate.xml:3454 msgid "sysctl" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3456 msgid "" "In kern_jail.c, the following sysctls are defined:" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3459 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "int jail_set_hostname_allowed = 1;\n" "SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,\n" " &jail_set_hostname_allowed, 0,\n" " \"Processes in jail can set their hostnames\");\n" "\n" "int jail_socket_unixiproute_only = 1;\n" "SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,\n" " &jail_socket_unixiproute_only, 0,\n" " \"Processes in jail are limited to creating UNIX/IPv4/route sockets " "only\");\n" "\n" "int jail_sysvipc_allowed = 0;\n" "SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,\n" " &jail_sysvipc_allowed, 0,\n" " \"Processes in jail can use System V IPC primitives\");\n" "\n" "static int jail_enforce_statfs = 2;\n" "SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,\n" " &jail_enforce_statfs, 0,\n" " \"Processes in jail cannot see all mounted file systems\");\n" "\n" "int jail_allow_raw_sockets = 0;\n" "SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,\n" " &jail_allow_raw_sockets, 0,\n" " \"Prison root can create raw sockets\");\n" "\n" "int jail_chflags_allowed = 0;\n" "SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,\n" " &jail_chflags_allowed, 0,\n" " \"Processes in jail can alter system file flags\");\n" "\n" "int jail_mount_allowed = 0;\n" "SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,\n" " &jail_mount_allowed, 0,\n" " \"Processes in jail can mount/unmount jail-friendly file systems\");" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3495 msgid "" "Each of these sysctls can be accessed by the user through the " "sysctl8 program. Throughout the kernel, these specific sysctls are " "recognized by their name. For example, the name of the first sysctl is " "security.jail.set_hostname_allowed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:3503 msgid "" "jail2 System Call" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3505 msgid "" "Like all system calls, the jail2 system call takes two " "arguments, struct thread *td and struct " "jail_args *uap. td is a pointer to the " "thread structure which describes the calling thread. In " "this context, uap is a pointer to the structure in which " "a pointer to the jail structure passed by the userland " "jail.c is contained. When I described the userland " "program before, you saw that the jail2 system call was given " "a jail structure as its own argument." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3518 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "/*\n" " * struct jail_args {\n" " * struct jail *jail;\n" " * };\n" " */\n" "int\n" "jail(struct thread *td, struct jail_args *uap)" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3527 msgid "" "Therefore, uap->jail can be used to access the " "jail structure which was passed to the system call. Next, " "the system call copies the jail structure into kernel " "space using the copyin9 function. " "copyin9 takes three arguments: the address of the data which is to be " "copied into kernel space, uap->jail, where to store " "it, j and the size of the storage. The jail structure pointed by uap->jail is copied into " "kernel space and is stored in another jail structure, " "j." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3540 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "error = copyin(uap->jail, &j, sizeof(j));" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3543 msgid "" "There is another important structure defined in jail.h. " "It is the prison structure. The prison " "structure is used exclusively within kernel space. Here is the definition of " "the prison structure." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3550 #, no-wrap msgid "" "/usr/include/sys/jail.h:\n" "struct prison {\n" " LIST_ENTRY(prison) pr_list; /* (a) all prisons */" "\n" " int pr_id; /* (c) prison id */\n" " int pr_ref; /* (p) refcount */\n" " char pr_path[MAXPATHLEN]; /* (c) chroot path */" "\n" " struct vnode *pr_root; /* (c) vnode to rdir " "*/\n" " char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname " "*/\n" " u_int32_t pr_ip; /* (c) ip addr host " "*/\n" " void *pr_linux; /* (p) linux abi */\n" " int pr_securelevel; /* (p) securelevel */" "\n" " struct task pr_task; /* (d) destroy task " "*/\n" " struct mtx pr_mtx;\n" " void **pr_slots; /* (p) additional data " "*/\n" "};" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3566 msgid "" "The jail2 system call then allocates memory for a " "prison structure and copies data between the " "jail and prison structure." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3571 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);\n" "...\n" "error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);\n" "if (error)\n" " goto e_killmtx;\n" "...\n" "error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), " "0);\n" "if (error)\n" " goto e_dropvnref;\n" "pr->pr_ip = j.ip_number;" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3583 msgid "" "Next, we will discuss another important system call " "jail_attach2, which implements the function to put a process " "into the jail." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3587 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "/*\n" " * struct jail_attach_args {\n" " * int jid;\n" " * };\n" " */\n" "int\n" "jail_attach(struct thread *td, struct jail_attach_args *uap)" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3596 msgid "" "This system call makes the changes that can distinguish a jailed process " "from those unjailed ones. To understand what " "jail_attach2 does for us, certain background information is " "needed." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3601 msgid "" "On FreeBSD, each kernel visible thread is identified by its thread structure, while the processes are described by their " "proc structures. You can find the definitions of the " "thread and proc structure in " "/usr/include/sys/proc.h. For example, the td argument in any system call is actually a pointer to the calling " "thread's thread structure, as stated before. The " "td_proc member in the thread structure " "pointed by td is a pointer to the proc " "structure which represents the process that contains the thread represented " "by td. The proc structure contains " "members which can describe the owner's identity(p_ucred), " "the process resource limits(p_limit), and so on. In the " "ucred structure pointed by p_ucred " "member in the proc structure, there is a pointer to the " "prison structure(cr_prison)." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3625 #, no-wrap msgid "" "/usr/include/sys/proc.h:\n" "struct thread {\n" " ...\n" " struct proc *td_proc;\n" " ...\n" "};\n" "struct proc {\n" " ...\n" " struct ucred *p_ucred;\n" " ...\n" "};\n" "/usr/include/sys/ucred.h\n" "struct ucred {\n" " ...\n" " struct prison *cr_prison;\n" " ...\n" "};" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3643 msgid "" "In kern_jail.c, the function jail() " "then calls function jail_attach() with a given " "jid. And jail_attach() calls function " "change_root() to change the root directory of the calling " "process. The jail_attach() then creates a new " "ucred structure, and attaches the newly created " "ucred structure to the calling process after it has " "successfully attached the prison structure to the " "ucred structure. From then on, the calling process is " "recognized as jailed. When the kernel routine jailed() is " "called in the kernel with the newly created ucred " "structure as its argument, it returns 1 to tell that the credential is " "connected with a jail. The public ancestor " "process of all the process forked within the jail, is the process which runs jail8, as it calls the " "jail2 system call. When a program is executed through " "execve2, it inherits the jailed property of its parent's " "ucred structure, therefore it has a jailed " "ucred structure." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3669 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c\n" "int\n" "jail(struct thread *td, struct jail_args *uap)\n" "{\n" "...\n" " struct jail_attach_args jaa;\n" "...\n" " error = jail_attach(td, &jaa);\n" " if (error)\n" " goto e_dropprref;\n" "...\n" "}\n" "\n" "int\n" "jail_attach(struct thread *td, struct jail_attach_args *uap)\n" "{\n" " struct proc *p;\n" " struct ucred *newcred, *oldcred;\n" " struct prison *pr;\n" "...\n" " p = td->td_proc;\n" "...\n" " pr = prison_find(uap->jid);\n" "...\n" " change_root(pr->pr_root, td);\n" "...\n" " newcred->cr_prison = pr;\n" " p->p_ucred = newcred;\n" "...\n" "}" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:3700 msgid "" "When a process is forked from its parent process, the " "fork2 system call uses crhold() to maintain the " "credential for the newly forked process. It inherently keep the newly forked " "child's credential consistent with its parent, so the child process is also " "jailed." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:3707 #, no-wrap msgid "" "/usr/src/sys/kern/kern_fork.c:\n" "p2->p_ucred = crhold(td->td_ucred);\n" "...\n" "td2->td_ucred = crhold(p2->p_ucred);" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:3716 msgid "Restrictions" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:3718 msgid "" "Throughout the kernel there are access restrictions relating to jailed " "processes. Usually, these restrictions only check whether the process is " "jailed, and if so, returns an error. For example:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:3723 #, no-wrap msgid "if (jailed(td->td_ucred))\n" " return (EPERM);" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3727 msgid "SysV IPC" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3729 msgid "System V IPC" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3731 msgid "" "System V IPC is based on messages. Processes can send each other these " "messages which tell them how to act. The functions which deal with messages " "are: msgctl3, msgget3, " "msgsnd3 and msgrcv3. Earlier, I mentioned " "that there were certain sysctls you could turn on or off in order to affect " "the behavior of jail. One of these sysctls was " "security.jail.sysvipc_allowed. By default, this sysctl is " "set to 0. If it were set to 1, it would defeat the whole purpose of having a " "jail; privileged users from the " "jail would be able to affect processes outside " "the jailed environment. The difference between a message and a signal is " "that the message only consists of the signal number." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3746 msgid "/usr/src/sys/kern/sysv_msg.c:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3750 msgid "" "msgget(key, msgflg): msgget returns " "(and possibly creates) a message descriptor that designates a message queue " "for use in other functions." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3757 msgid "" "msgctl(msgid, cmd, buf): Using this function, a process " "can query the status of a message descriptor." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3763 msgid "" "msgsnd(msgid, msgp, msgsz, msgflg): msgsnd sends a message to a process." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3769 msgid "" "msgrcv(msgid, msgp, msgsz, msgtyp, msgflg): a process " "receives messages using this function" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3775 msgid "" "In each of the system calls corresponding to these functions, there is this " "conditional:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3778 #, no-wrap msgid "" "/usr/src/sys/kern/sysv_msg.c:\n" "if (!jail_sysvipc_allowed && jailed(td->td_ucred))\n" " return (ENOSYS);" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3782 msgid "semaphores" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3784 msgid "" "Semaphore system calls allow processes to synchronize execution by doing a " "set of operations atomically on a set of semaphores. Basically semaphores " "provide another way for processes lock resources. However, process waiting " "on a semaphore, that is being used, will sleep until the resources are " "relinquished. The following semaphore system calls are blocked inside a " "jail: semget2, " "semctl2 and semop2." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3793 msgid "/usr/src/sys/kern/sysv_sem.c:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3797 msgid "" "semctl(semid, semnum, cmd, ...): semctl does the specified cmd on the semaphore queue " "indicated by semid." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3803 msgid "" "semget(key, nsems, flag): semget " "creates an array of semaphores, corresponding to key." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3807 msgid "" "key and flag take on the same meaning as they do in msgget." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3811 msgid "" "semop(semid, array, nops): semop " "performs a group of operations indicated by array, to the " "set of semaphores identified by semid." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3818 msgid "shared memory" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3820 msgid "" "System V IPC allows for processes to share memory. Processes can communicate " "directly with each other by sharing parts of their virtual address space and " "then reading and writing data stored in the shared memory. These system " "calls are blocked within a jailed environment: " "shmdt2, shmat2, " "shmctl2 and shmget2." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3827 msgid "/usr/src/sys/kern/sysv_shm.c:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3830 msgid "" "shmctl(shmid, cmd, buf): shmctl does " "various control operations on the shared memory region identified by " "shmid." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3836 msgid "" "shmget(key, size, flag): shmget " "accesses or creates a shared memory region of size bytes." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3842 msgid "" "shmat(shmid, addr, flag): shmat " "attaches a shared memory region identified by shmid to " "the address space of a process." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:3848 msgid "" "shmdt(addr): shmdt detaches the shared " "memory region previously attached at addr." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3857 msgid "Sockets" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3859 msgid "sockets" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3861 msgid "" "Jail treats the " "socket2 system call and related lower-level socket functions in a " "special manner. In order to determine whether a certain socket is allowed to " "be created, it first checks to see if the sysctl security.jail." "socket_unixiproute_only is set. If set, sockets are only allowed " "to be created if the family specified is either PF_LOCAL, " "PF_INET or PF_ROUTE. Otherwise, it " "returns an error." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3872 #, no-wrap msgid "" "/usr/src/sys/kern/uipc_socket.c:\n" "int\n" "socreate(int dom, struct socket **aso, int type, int proto,\n" " struct ucred *cred, struct thread *td)\n" "{\n" " struct protosw *prp;\n" "...\n" " if (jailed(cred) && jail_socket_unixiproute_only &&\n" " prp->pr_domain->dom_family != PF_LOCAL &&\n" " prp->pr_domain->dom_family != PF_INET &&\n" " prp->pr_domain->dom_family != PF_ROUTE) {\n" " return (EPROTONOSUPPORT);\n" " }\n" "...\n" "}" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3890 msgid "Berkeley Packet Filter" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3892 msgid "Berkeley Packet Filter" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3893 msgid "data link layer" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3895 msgid "" "The Berkeley Packet Filter provides a raw " "interface to data link layers in a protocol independent fashion. " "BPF is now controlled by the " "devfs8 whether it can be used in a jailed environment." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:3904 msgid "Protocols" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:3906 msgid "protocols" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3908 msgid "" "There are certain protocols which are very common, such as TCP, UDP, IP and " "ICMP. IP and ICMP are on the same level: the network layer 2. There are " "certain precautions which are taken in order to prevent a jailed process " "from binding a protocol to a certain address only if the nam parameter is set. nam is a pointer to a " "sockaddr structure, which describes the address on which " "to bind the service. A more exact definition is that sockaddr \"may be used as a template for referring to the identifying tag " "and length of each address\". In the function in_pcbbind_setup(), sin is a pointer to a sockaddr_in structure, which contains the port, address, length and domain " "family of the socket which is to be bound. Basically, this disallows any " "processes from jail to be able to specify the " "address that does not belong to the jail in which " "the calling process exists." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3929 #, no-wrap msgid "" "/usr/src/sys/netinet/in_pcb.c:\n" "int\n" "in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,\n" " u_short *lportp, struct ucred *cred)\n" "{\n" " ...\n" " struct sockaddr_in *sin;\n" " ...\n" " if (nam) {\n" " sin = (struct sockaddr_in *)nam;\n" " ...\n" " if (sin->sin_addr.s_addr != INADDR_ANY)\n" " if (prison_ip(cred, 0, &sin->sin_addr.s_addr))\n" " return(EINVAL);\n" " ...\n" " if (lport) {\n" " ...\n" " if (prison && prison_ip(cred, 0, &sin->sin_addr." "s_addr))\n" " return (EADDRNOTAVAIL);\n" " ...\n" " }\n" " }\n" " if (lport == 0) {\n" " ...\n" " if (laddr.s_addr != INADDR_ANY)\n" " if (prison_ip(cred, 0, &laddr.s_addr))\n" " return (EINVAL);\n" " ...\n" " }\n" "...\n" " if (prison_ip(cred, 0, &laddr.s_addr))\n" " return (EINVAL);\n" "...\n" "}" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:3964 msgid "" "You might be wondering what function prison_ip() does. " "prison_ip() is given three arguments, a pointer to the " "credential(represented by cred), any flags, and an IP " "address. It returns 1 if the IP address does NOT belong to the " "jail or 0 otherwise. As you can see from the " "code, if it is indeed an IP address not belonging to the jail, the protocol is not allowed to bind to that address." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:3975 #, no-wrap msgid "" "/usr/src/sys/kern/kern_jail.c:\n" "int\n" "prison_ip(struct ucred *cred, int flag, u_int32_t *ip)\n" "{\n" " u_int32_t tmp;\n" "\n" " if (!jailed(cred))\n" " return (0);\n" " if (flag)\n" " tmp = *ip;\n" " else\n" " tmp = ntohl(*ip);\n" " if (tmp == INADDR_ANY) {\n" " if (flag)\n" " *ip = cred->cr_prison->pr_ip;\n" " else\n" " *ip = htonl(cred->cr_prison->pr_ip);\n" " return (0);\n" " }\n" " if (tmp == INADDR_LOOPBACK) {\n" " if (flag)\n" " *ip = cred->cr_prison->pr_ip;\n" " else\n" " *ip = htonl(cred->cr_prison->pr_ip);\n" " return (0);\n" " }\n" " if (cred->cr_prison->pr_ip != tmp)\n" " return (1);\n" " return (0);\n" "}" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4008 msgid "Filesystem" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:4010 msgid "filesystem" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4012 msgid "" "Even root users within the jail are not allowed to unset or modify any file flags, such as " "immutable, append-only, and undeleteable flags, if the securelevel is " "greater than 0." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:4018 #, no-wrap msgid "" "/usr/src/sys/ufs/ufs/ufs_vnops.c:\n" "static int\n" "ufs_setattr(ap)\n" " ...\n" "{\n" " ...\n" " if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {\n" " if (ip->i_flags\n" " & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {\n" " error = securelevel_gt(cred, 0);\n" " if (error)\n" " return (error);\n" " }\n" " ...\n" " }\n" "}\n" "/usr/src/sys/kern/kern_priv.c\n" "int\n" "priv_check_cred(struct ucred *cred, int priv, int flags)\n" "{\n" " ...\n" " error = prison_priv_check(cred, priv);\n" " if (error)\n" " return (error);\n" " ...\n" "}\n" "/usr/src/sys/kern/kern_jail.c\n" "int\n" "prison_priv_check(struct ucred *cred, int priv)\n" "{\n" " ...\n" " switch (priv) {\n" " ...\n" " case PRIV_VFS_SYSFLAGS:\n" " if (jail_chflags_allowed)\n" " return (0);\n" " else\n" " return (EPERM);\n" " ...\n" " }\n" " ...\n" "}" msgstr "" #. (itstool) path: chapter/title #: book.translate.xml:4071 msgid "The SYSINIT Framework" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:4073 msgid "SYSINIT" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:4074 msgid "dynamic initialization" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:4075 msgid "" "kernel initialization dynamic" msgstr "" #. (itstool) path: chapter/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:4077 book.translate.xml:15500 msgid "kernel modules" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:4078 msgid "kernel linker" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:4080 msgid "" "SYSINIT is the framework for a generic call sort and dispatch mechanism. " "FreeBSD currently uses it for the dynamic initialization of the kernel. " "SYSINIT allows FreeBSD's kernel subsystems to be reordered, and added, " "removed, and replaced at kernel link time when the kernel or one of its " "modules is loaded without having to edit a statically ordered initialization " "routing and recompile the kernel. This system also allows kernel modules, " "currently called KLD's, to be separately compiled, " "linked, and initialized at boot time and loaded even later while the system " "is already running. This is accomplished using the kernel linker and linker sets." msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:4098 msgid "Linker Set" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4100 msgid "" "A linker technique in which the linker gathers statically declared data " "throughout a program's source files into a single contiguously addressable " "unit of data." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4110 msgid "SYSINIT Operation" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:4112 msgid "linker sets" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4114 msgid "" "SYSINIT relies on the ability of the linker to take static data declared at " "multiple locations throughout a program's source and group it together as a " "single contiguous chunk of data. This linker technique is called a " "linker set. SYSINIT uses two linker sets to maintain two data " "sets containing each consumer's call order, function, and a pointer to the " "data to pass to that function." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4122 msgid "" "SYSINIT uses two priorities when ordering the functions for execution. The " "first priority is a subsystem ID giving an overall order for SYSINIT's " "dispatch of functions. Current predeclared ID's are in <sys/" "kernel.h> in the enum list sysinit_sub_id. " "The second priority used is an element order within the subsystem. Current " "predeclared subsystem element orders are in <sys/kernel.h> in the enum list sysinit_elem_order." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:4132 msgid "pseudo-devices" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4134 msgid "" "There are currently two uses for SYSINIT. Function dispatch at system " "startup and kernel module loads, and function dispatch at system shutdown " "and kernel module unload. Kernel subsystems often use system startup " "SYSINIT's to initialize data structures, for example the process scheduling " "subsystem uses a SYSINIT to initialize the run queue data structure. Device " "drivers should avoid using SYSINIT() directly. Instead " "drivers for real devices that are part of a bus structure should use " "DRIVER_MODULE() to provide a function that detects the " "device and, if it is present, initializes the device. It will do a few " "things specific to devices and then call SYSINIT() itself." " For pseudo-devices, which are not part of a bus structure, use " "DEV_MODULE()." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4152 msgid "Using SYSINIT" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:4160 #, no-wrap msgid "<sys/kernel.h>" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:4166 #, no-wrap msgid "" "SYSINIT(uniquifier, subsystem, order, func, ident)\n" "SYSUNINIT(uniquifier, subsystem, order, func, ident)" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4172 msgid "Startup" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4174 msgid "" "The SYSINIT() macro creates the necessary SYSINIT data in " "SYSINIT's startup data set for SYSINIT to sort and dispatch a function at " "system startup and module load. SYSINIT() takes a " "uniquifier that SYSINIT uses to identify the particular function dispatch " "data, the subsystem order, the subsystem element order, the function to " "call, and the data to pass the function. All functions must take a constant " "pointer argument." msgstr "" #. (itstool) path: example/title #: book.translate.xml:4185 msgid "Example of a SYSINIT()" msgstr "" #. (itstool) path: example/programlisting #: book.translate.xml:4187 #, no-wrap msgid "" "#include <sys/kernel.h>\n" "\n" "void foo_null(void *unused)\n" "{\n" " foo_doo();\n" "}\n" "SYSINIT(foo, SI_SUB_FOO, SI_ORDER_FOO, foo_null, NULL);\n" "\n" "struct foo foo_voodoo = {\n" " FOO_VOODOO;\n" "}\n" "\n" "void foo_arg(void *vdata)\n" "{\n" " struct foo *foo = (struct foo *)vdata;\n" " foo_data(foo);\n" "}\n" "SYSINIT(bar, SI_SUB_FOO, SI_ORDER_FOO, foo_arg, &foo_voodoo);\n" " " msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4208 msgid "" "Note that SI_SUB_FOO and SI_ORDER_FOO " "need to be in the sysinit_sub_id and " "sysinit_elem_order enum's as mentioned above. Either use " "existing ones or add your own to the enum's. You can also use math for fine-" "tuning the order a SYSINIT will run in. This example shows a SYSINIT that " "needs to be run just barely before the SYSINIT's that handle tuning kernel " "parameters." msgstr "" #. (itstool) path: example/title #: book.translate.xml:4219 msgid "Example of Adjusting SYSINIT() Order" msgstr "" #. (itstool) path: example/programlisting #: book.translate.xml:4221 #, no-wrap msgid "" "static void\n" "mptable_register(void *dummy __unused)\n" "{\n" "\n" " apic_register_enumerator(&mptable_enumerator);\n" "}\n" "\n" "SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,\n" " mptable_register, NULL);" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4234 msgid "Shutdown" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4236 msgid "" "The SYSUNINIT() macro behaves similarly to the " "SYSINIT() macro except that it adds the SYSINIT data to " "SYSINIT's shutdown data set." msgstr "" #. (itstool) path: example/title #: book.translate.xml:4241 msgid "Example of a SYSUNINIT()" msgstr "" #. (itstool) path: example/programlisting #: book.translate.xml:4243 #, no-wrap msgid "" "#include <sys/kernel.h>\n" "\n" "void foo_cleanup(void *unused)\n" "{\n" " foo_kill();\n" "}\n" "SYSUNINIT(foobar, SI_SUB_FOO, SI_ORDER_FOO, foo_cleanup, NULL);\n" "\n" "struct foo_stack foo_stack = {\n" " FOO_STACK_VOODOO;\n" "}\n" "\n" "void foo_flush(void *vdata)\n" "{\n" "}\n" "SYSUNINIT(barfoo, SI_SUB_FOO, SI_ORDER_FOO, foo_flush, &foo_stack);\n" " " msgstr "" #. (itstool) path: info/title #: book.translate.xml:4301 msgid "The TrustedBSD MAC Framework" msgstr "" #. (itstool) path: affiliation/address #: book.translate.xml:4311 #, no-wrap msgid "\n" " chris@FreeBSD.org\n" " " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:4304 msgid "" " Chris Costello TrustedBSD Project <_:address-1/" "> " msgstr "" #. (itstool) path: affiliation/address #: book.translate.xml:4324 #, no-wrap msgid "\n" " rwatson@FreeBSD.org\n" " " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:4317 msgid "" " Robert Watson TrustedBSD Project <_:address-1/" "> " msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4333 msgid "MAC Documentation Copyright" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4335 msgid "" "This documentation was developed for the FreeBSD Project by Chris Costello " "at Safeport Network Services and Network Associates Laboratories, the " "Security Research Division of Network Associates, Inc. under DARPA/SPAWAR " "contract N66001-01-C-8035 (CBOSS), as part of the DARPA CHATS " "research program." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4342 msgid "" "Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, " "HTML, PDF, PostScript, RTF and so forth) with or without modification, are " "permitted provided that the following conditions are met:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4349 msgid "" "Redistributions of source code (SGML DocBook) must retain the above " "copyright notice, this list of conditions and the following disclaimer as " "the first lines of this file unmodified." msgstr "" #. (itstool) path: important/para #: book.translate.xml:4366 msgid "" "THIS DOCUMENTATION IS PROVIDED BY THE NETWORKS ASSOCIATES TECHNOLOGY, INC " "\"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 NETWORKS ASSOCIATES TECHNOLOGY, " "INC 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 DOCUMENTATION, EVEN IF ADVISED OF " "THE POSSIBILITY OF SUCH DAMAGE." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4385 msgid "" "FreeBSD includes experimental support for several mandatory access control " "policies, as well as a framework for kernel security extensibility, the " "TrustedBSD MAC Framework. The MAC Framework is a pluggable access control " "framework, permitting new security policies to be easily linked into the " "kernel, loaded at boot, or loaded dynamically at run-time. The framework " "provides a variety of features to make it easier to implement new security " "policies, including the ability to easily tag security labels (such as " "confidentiality information) onto system objects." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4396 msgid "" "This chapter introduces the MAC policy framework and provides documentation " "for a sample MAC policy module." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4402 book.translate.xml:14904 book.translate.xml:16074 #: book.translate.xml:21700 book.translate.xml:22815 msgid "Introduction" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4404 msgid "" "The TrustedBSD MAC framework provides a mechanism to allow the compile-time " "or run-time extension of the kernel access control model. New system " "policies may be implemented as kernel modules and linked to the kernel; if " "multiple policy modules are present, their results will be composed. The MAC " "Framework provides a variety of access control infrastructure services to " "assist policy writers, including support for transient and persistent policy-" "agnostic object security labels. This support is currently considered " "experimental." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4414 msgid "" "This chapter provides information appropriate for developers of policy " "modules, as well as potential consumers of MAC-enabled environments, to " "learn about how the MAC Framework supports access control extension of the " "kernel." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4421 msgid "Policy Background" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4423 msgid "" "Mandatory Access Control (MAC), refers to a set of access control policies " "that are mandatorily enforced on users by the operating system. MAC policies " "may be contrasted with Discretionary Access Control (DAC) protections, by " "which non-administrative users may (at their discretion) protect objects. In " "traditional UNIX systems, DAC protections include file permissions and " "access control lists; MAC protections include process controls preventing " "inter-user debugging and firewalls. A variety of MAC policies have been " "formulated by operating system designers and security researches, including " "the Multi-Level Security (MLS) confidentiality policy, the Biba integrity " "policy, Role-Based Access Control (RBAC), Domain and Type Enforcement (DTE), " "and Type Enforcement (TE). Each model bases decisions on a variety of " "factors, including user identity, role, and security clearance, as well as " "security labels on objects representing concepts such as data sensitivity " "and integrity." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4441 msgid "" "The TrustedBSD MAC Framework is capable of supporting policy modules that " "implement all of these policies, as well as a broad class of system " "hardening policies, which may use existing security attributes, such as user " "and group IDs, as well as extended attributes on files, and other system " "properties. In addition, despite the name, the MAC Framework can also be " "used to implement purely discretionary policies, as policy modules are given " "substantial flexibility in how they authorize protections." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4453 msgid "MAC Framework Kernel Architecture" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4455 msgid "" "The TrustedBSD MAC Framework permits kernel modules to extend the operating " "system security policy, as well as providing infrastructure functionality " "required by many access control modules. If multiple policies are " "simultaneously loaded, the MAC Framework will usefully (for some definition " "of useful) compose the results of the policies." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4463 msgid "Kernel Elements" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4465 msgid "The MAC Framework contains a number of kernel elements:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4470 msgid "Framework management interfaces" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4473 msgid "Concurrency and synchronization primitives." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4476 msgid "Policy registration" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4479 msgid "Extensible security label for kernel objects" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4482 msgid "Policy entry point composition operators" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4485 msgid "Label management primitives" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4488 msgid "Entry point API invoked by kernel services" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4491 msgid "Entry point API to policy modules" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4494 msgid "" "Entry points implementations (policy life cycle, object life cycle/label " "management, access control checks)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4499 msgid "Policy-agnostic label-management system calls" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4502 msgid "mac_syscall() multiplex system call" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4506 msgid "Various security policies implemented as MAC policy modules" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4513 msgid "Framework Management Interfaces" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4515 msgid "" "The TrustedBSD MAC Framework may be directly managed using sysctl's, loader " "tunables, and system calls." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4518 msgid "" "In most cases, sysctl's and loader tunables of the same name modify the same " "parameters, and control behavior such as enforcement of protections relating " "to various kernel subsystems. In addition, if MAC debugging support is " "compiled into the kernel, several counters will be maintained tracking label " "allocation. It is generally advisable that per-subsystem enforcement " "controls not be used to control policy behavior in production environments, " "as they broadly impact the operation of all active policies. Instead, per-" "policy controls should be preferred, as they provide greater granularity and " "greater operational consistency for policy modules." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4531 msgid "" "Loading and unloading of policy modules is performed using the system module " "management system calls and other system interfaces, including boot loader " "variables; policy modules will have the opportunity to influence load and " "unload events, including preventing undesired unloading of the policy." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4539 msgid "Policy List Concurrency and Synchronization" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4541 msgid "" "As the set of active policies may change at run-time, and the invocation of " "entry points is non-atomic, synchronization is required to prevent loading " "or unloading of policies while an entry point invocation is in progress, " "freezing the set of active policies for the duration. This is accomplished " "by means of a framework busy count: whenever an entry point is entered, the " "busy count is incremented; whenever it is exited, the busy count is " "decremented. While the busy count is elevated, policy list changes are not " "permitted, and threads attempting to modify the policy list will sleep until " "the list is not busy. The busy count is protected by a mutex, and a " "condition variable is used to wake up sleepers waiting on policy list " "modifications. One side effect of this synchronization model is that " "recursion into the MAC Framework from within a policy module is permitted, " "although not generally used." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4558 msgid "" "Various optimizations are used to reduce the overhead of the busy count, " "including avoiding the full cost of incrementing and decrementing if the " "list is empty or contains only static entries (policies that are loaded " "before the system starts, and cannot be unloaded). A compile-time option is " "also provided which prevents any change in the set of loaded policies at run-" "time, which eliminates the mutex locking costs associated with supporting " "dynamically loaded and unloaded policies as synchronization is no longer " "required." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4569 msgid "" "As the MAC Framework is not permitted to block in some entry points, a " "normal sleep lock cannot be used; as a result, it is possible for the load " "or unload attempt to block for a substantial period of time waiting for the " "framework to become idle." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4577 msgid "Label Synchronization" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4579 msgid "" "As kernel objects of interest may generally be accessed from more than one " "thread at a time, and simultaneous entry of more than one thread into the " "MAC Framework is permitted, security attribute storage maintained by the MAC " "Framework is carefully synchronized. In general, existing kernel " "synchronization on kernel object data is used to protect MAC Framework " "security labels on the object: for example, MAC labels on sockets are " "protected using the existing socket mutex. Likewise, semantics for " "concurrent access are generally identical to those of the container objects: " "for credentials, copy-on-write semantics are maintained for label contents " "as with the remainder of the credential structure. The MAC Framework asserts " "necessary locks on objects when invoked with an object reference. Policy " "authors must be aware of these synchronization semantics, as they will " "sometimes limit the types of accesses permitted on labels: for example, when " "a read-only reference to a credential is passed to a policy via an entry " "point, only read operations are permitted on the label state attached to the " "credential." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4602 msgid "Policy Synchronization and Concurrency" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4604 msgid "" "Policy modules must be written to assume that many kernel threads may " "simultaneously enter one more policy entry points due to the parallel and " "preemptive nature of the FreeBSD kernel. If the policy module makes use of " "mutable state, this may require the use of synchronization primitives within " "the policy to prevent inconsistent views on that state resulting in " "incorrect operation of the policy. Policies will generally be able to make " "use of existing FreeBSD synchronization primitives for this purpose, " "including mutexes, sleep locks, condition variables, and counting semaphores." " However, policies should be written to employ these primitives carefully, " "respecting existing kernel lock orders, and recognizing that some entry " "points are not permitted to sleep, limiting the use of primitives in those " "entry points to mutexes and wakeup operations." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4620 msgid "" "When policy modules call out to other kernel subsystems, they will generally " "need to release any in-policy locks in order to avoid violating the kernel " "lock order or risking lock recursion. This will maintain policy locks as " "leaf locks in the global lock order, helping to avoid deadlock." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4628 msgid "Policy Registration" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4630 msgid "" "The MAC Framework maintains two lists of active policies: a static list, and " "a dynamic list. The lists differ only with regards to their locking " "semantics: an elevated reference count is not required to make use of the " "static list. When kernel modules containing MAC Framework policies are " "loaded, the policy module will use SYSINIT to invoke a " "registration function; when a policy module is unloaded, SYSINIT will likewise invoke a de-registration function. Registration may " "fail if a policy module is loaded more than once, if insufficient resources " "are available for the registration (for example, the policy might require " "labeling and insufficient labeling state might be available), or other " "policy prerequisites might not be met (some policies may only be loaded " "prior to boot). Likewise, de-registration may fail if a policy is flagged as " "not unloadable." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4649 msgid "Entry Points" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4651 msgid "" "Kernel services interact with the MAC Framework in two ways: they invoke a " "series of APIs to notify the framework of relevant events, and they provide " "a policy-agnostic label structure pointer in security-relevant objects. The " "label pointer is maintained by the MAC Framework via label management entry " "points, and permits the Framework to offer a labeling service to policy " "modules through relatively non-invasive changes to the kernel subsystem " "maintaining the object. For example, label pointers have been added to " "processes, process credentials, sockets, pipes, vnodes, Mbufs, network " "interfaces, IP reassembly queues, and a variety of other security-relevant " "structures. Kernel services also invoke the MAC Framework when they perform " "important security decisions, permitting policy modules to augment those " "decisions based on their own criteria (possibly including data stored in " "security labels). Most of these security critical decisions will be explicit " "access control checks; however, some affect more general decision functions " "such as packet matching for sockets and label transition at program " "execution." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4674 msgid "Policy Composition" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4676 msgid "" "When more than one policy module is loaded into the kernel at a time, the " "results of the policy modules will be composed by the framework using a " "composition operator. This operator is currently hard-coded, and requires " "that all active policies must approve a request for it to return success. As " "policies may return a variety of error conditions (success, access denied, " "object does not exist, ...), a precedence operator selects the resulting " "error from the set of errors returned by policies. In general, errors " "indicating that an object does not exist will be preferred to errors " "indicating that access to an object is denied. While it is not guaranteed " "that the resulting composition will be useful or secure, we have found that " "it is for many useful selections of policies. For example, traditional " "trusted systems often ship with two or more policies using a similar " "composition." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4694 msgid "Labeling Support" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4696 msgid "" "As many interesting access control extensions rely on security labels on " "objects, the MAC Framework provides a set of policy-agnostic label " "management system calls covering a variety of user-exposed objects. Common " "label types include partition identifiers, sensitivity labels, integrity " "labels, compartments, domains, roles, and types. By policy agnostic, we mean " "that policy modules are able to completely define the semantics of meta-data " "associated with an object. Policy modules participate in the internalization " "and externalization of string-based labels provides by user applications, " "and can expose multiple label elements to applications if desired." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4709 msgid "" "In-memory labels are stored in slab-allocated struct label, which consists of a fixed-length " "array of unions, each holding a void * pointer and a " "long. Policies registering for label storage will be " "assigned a \"slot\" identifier, which may be used to dereference the label " "storage. The semantics of the storage are left entirely up to the policy " "module: modules are provided with a variety of entry points associated with " "the kernel object life cycle, including initialization, association/" "creation, and destruction. Using these interfaces, it is possible to " "implement reference counting and other storage models. Direct access to the " "object structure is generally not required by policy modules to retrieve a " "label, as the MAC Framework generally passes both a pointer to the object " "and a direct pointer to the object's label into entry points. The primary " "exception to this rule is the process credential, which must be manually " "dereferenced to access the credential label. This may change in future " "revisions of the MAC Framework." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4728 msgid "" "Initialization entry points frequently include a sleeping disposition flag " "indicating whether or not an initialization is permitted to sleep; if " "sleeping is not permitted, a failure may be returned to cancel allocation of " "the label (and hence object). This may occur, for example, in the network " "stack during interrupt handling, where sleeping is not permitted, or while " "the caller holds a mutex. Due to the performance cost of maintaining labels " "on in-flight network packets (Mbufs), policies must specifically declare a " "requirement that Mbuf labels be allocated. Dynamically loaded policies " "making use of labels must be able to handle the case where their init " "function has not been called on an object, as objects may already exist when " "the policy is loaded. The MAC Framework guarantees that uninitialized label " "slots will hold a 0 or NULL value, which policies may use to detect " "uninitialized values. However, as allocation of Mbuf labels is conditional, " "policies must also be able to handle a NULL label pointer for Mbufs if they " "have been loaded dynamically." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4747 msgid "" "In the case of file system labels, special support is provided for the " "persistent storage of security labels in extended attributes. Where " "available, extended attribute transactions are used to permit consistent " "compound updates of security labels on vnodes--currently this support is " "present only in the UFS2 file system. Policy authors may choose to implement " "multilabel file system object labels using one (or more) extended attributes." " For efficiency reasons, the vnode label (v_label) is a " "cache of any on-disk label; policies are able to load values into the cache " "when the vnode is instantiated, and update the cache as needed. As a result, " "the extended attribute need not be directly accessed with every access " "control check." msgstr "" #. (itstool) path: note/para #: book.translate.xml:4762 msgid "" "Currently, if a labeled policy permits dynamic unloading, its state slot " "cannot be reclaimed, which places a strict (and relatively low) bound on the " "number of unload-reload operations for labeled policies." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4770 msgid "System Calls" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4772 msgid "" "The MAC Framework implements a number of system calls: most of these calls " "support the policy-agnostic label retrieval and manipulation APIs exposed to " "user applications." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4777 msgid "" "The label management calls accept a label description structure, struct mac, which contains a series of MAC " "label elements. Each element contains a character string name, and character " "string value. Each policy will be given the chance to claim a particular " "element name, permitting policies to expose multiple independent elements if " "desired. Policy modules perform the internalization and externalization " "between kernel labels and user-provided labels via entry points, permitting " "a variety of semantics. Label management system calls are generally wrapped " "by user library functions to perform memory allocation and error handling, " "simplifying user applications that must manage labels." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4791 msgid "" "The following MAC-related system calls are present in the FreeBSD kernel:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4796 msgid "" "mac_get_proc() may be used to retrieve the label of the " "current process." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4801 msgid "" "mac_set_proc() may be used to request a change in the " "label of the current process." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4807 msgid "" "mac_get_fd() may be used to retrieve the label of an " "object (file, socket, pipe, ...) referenced by a file descriptor." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4813 msgid "" "mac_get_file() may be used to retrieve the label of an " "object referenced by a file system path." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4819 msgid "" "mac_set_fd() may be used to request a change in the " "label of an object (file, socket, pipe, ...) referenced by a file descriptor." "" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4825 msgid "" "mac_set_file() may be used to request a change in the " "label of an object referenced by a file system path." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4831 msgid "" "mac_syscall() permits policy modules to create new " "system calls without modifying the system call table; it accepts a target " "policy name, operation number, and opaque argument for use by the policy." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4839 msgid "" "mac_get_pid() may be used to request the label of " "another process by process id." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4844 msgid "" "mac_get_link() is identical to " "mac_get_file(), only it will not follow a symbolic link " "if it is the final entry in the path, so may be used to retrieve the label " "on a symlink." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4852 msgid "" "mac_set_link() is identical to " "mac_set_file(), only it will not follow a symbolic link " "if it is the final entry in a path, so may be used to manipulate the label " "on a symlink." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4860 msgid "" "mac_execve() is identical to the execve() system call, only it also accepts a requested label to set the " "process label to when beginning execution of a new program. This change in " "label on execution is referred to as a \"transition\"." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4869 msgid "" "mac_get_peer(), actually implemented via a socket " "option, retrieves the label of a remote peer on a socket, if available." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4875 msgid "" "In addition to these system calls, the SIOCSIGMAC and " "SIOCSIFMAC network interface ioctls permit the labels on " "network interfaces to be retrieved and set." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:4884 msgid "MAC Policy Architecture" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:4886 msgid "" "Security policies are either linked directly into the kernel, or compiled " "into loadable kernel modules that may be loaded at boot, or dynamically " "using the module loading system calls at runtime. Policy modules interact " "with the system through a set of declared entry points, providing access to " "a stream of system events and permitting the policy to influence access " "control decisions. Each policy contains a number of elements:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4897 msgid "Optional configuration parameters for policy." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4901 msgid "Centralized implementation of the policy logic and parameters." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4905 msgid "" "Optional implementation of policy life cycle events, such as initialization " "and destruction." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4909 msgid "" "Optional support for initializing, maintaining, and destroying labels on " "selected kernel objects." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4914 msgid "" "Optional support for user process inspection and modification of labels on " "selected objects." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4919 msgid "" "Implementation of selected access control entry points that are of interest " "to the policy." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4923 msgid "" "Declaration of policy identity, module entry points, and policy properties." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4929 msgid "Policy Declaration" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4931 msgid "" "Modules may be declared using the MAC_POLICY_SET() " "macro, which names the policy, provides a reference to the MAC entry point " "vector, provides load-time flags determining how the policy framework should " "handle the policy, and optionally requests the allocation of label state by " "the framework." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:4938 #, no-wrap msgid "" "static struct mac_policy_ops mac_policy_ops =\n" "{\n" " .mpo_destroy = mac_policy_destroy,\n" " .mpo_init = mac_policy_init,\n" " .mpo_init_bpfdesc_label = mac_policy_init_bpfdesc_label,\n" " .mpo_init_cred_label = mac_policy_init_label,\n" "/* ... */\n" " .mpo_check_vnode_setutimes = mac_policy_check_vnode_setutimes,\n" " .mpo_check_vnode_stat = mac_policy_check_vnode_stat,\n" " .mpo_check_vnode_write = mac_policy_check_vnode_write,\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4950 msgid "" "The MAC policy entry point vector, mac_policy_ops in this example, associates functions defined in " "the module with specific entry points. A complete listing of available entry " "points and their prototypes may be found in the MAC entry point reference " "section. Of specific interest during module registration are the ." "mpo_destroy and .mpo_init entry points. ." "mpo_init will be invoked once a policy is successfully registered " "with the module framework but prior to any other entry points becoming " "active. This permits the policy to perform any policy-specific allocation " "and initialization, such as initialization of any data or locks. ." "mpo_destroy will be invoked when a policy module is unloaded to " "permit releasing of any allocated memory and destruction of locks. " "Currently, these two entry points are invoked with the MAC policy list mutex " "held to prevent any other entry points from being invoked: this will be " "changed, but in the mean time, policies should be careful about what kernel " "primitives they invoke so as to avoid lock ordering or sleeping problems." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4972 msgid "" "The policy declaration's module name field exists so that the module may be " "uniquely identified for the purposes of module dependencies. An appropriate " "string should be selected. The full string name of the policy is displayed " "to the user via the kernel log during load and unload events, and also " "exported when providing status information to userland processes." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:4982 msgid "Policy Flags" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:4984 msgid "" "The policy declaration flags field permits the module to provide the " "framework with information about its capabilities at the time the module is " "loaded. Currently, three flags are defined:" msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:4991 msgid "MPC_LOADTIME_FLAG_UNLOADOK" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:4994 msgid "" "This flag indicates that the policy module may be unloaded. If this flag is " "not provided, then the policy framework will reject requests to unload the " "module. This flag might be used by modules that allocate label state and are " "unable to free that state at runtime." msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:5004 msgid "MPC_LOADTIME_FLAG_NOTLATE" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:5007 msgid "" "This flag indicates that the policy module must be loaded and initialized " "early in the boot process. If the flag is specified, attempts to register " "the module following boot will be rejected. The flag may be used by policies " "that require pervasive labeling of all system objects, and cannot handle " "objects that have not been properly initialized by the policy." msgstr "" #. (itstool) path: varlistentry/term #: book.translate.xml:5018 msgid "MPC_LOADTIME_FLAG_LABELMBUFS" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:5021 msgid "" "This flag indicates that the policy module requires labeling of Mbufs, and " "that memory should always be allocated for the storage of Mbuf labels. By " "default, the MAC Framework will not allocate label storage for Mbufs unless " "at least one loaded policy has this flag set. This measurably improves " "network performance when policies do not require Mbuf labeling. A kernel " "option, MAC_ALWAYS_LABEL_MBUF, exists to force the MAC " "Framework to allocate Mbuf label storage regardless of the setting of this " "flag, and may be useful in some environments." msgstr "" #. (itstool) path: note/para #: book.translate.xml:5037 msgid "" "Policies using the MPC_LOADTIME_FLAG_LABELMBUFS without " "the MPC_LOADTIME_FLAG_NOTLATE flag set must be able to " "correctly handle NULL Mbuf label pointers passed into " "entry points. This is necessary as in-flight Mbufs without label storage may " "persist after a policy enabling Mbuf labeling has been loaded. If a policy " "is loaded before the network subsystem is active (i.e., the policy is not " "being loaded late), then all Mbufs are guaranteed to have label storage." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:5051 msgid "Policy Entry Points" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:5053 msgid "" "Four classes of entry points are offered to policies registered with the " "framework: entry points associated with the registration and management of " "policies, entry points denoting initialization, creation, destruction, and " "other life cycle events for kernel objects, events associated with access " "control decisions that the policy module may influence, and calls associated " "with the management of labels on objects. In addition, a " "mac_syscall() entry point is provided so that policies " "may extend the kernel interface without registering new system calls." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:5064 msgid "" "Policy module writers should be aware of the kernel locking strategy, as " "well as what object locks are available during which entry points. Writers " "should attempt to avoid deadlock scenarios by avoiding grabbing non-leaf " "locks inside of entry points, and also follow the locking protocol for " "object access and modification. In particular, writers should be aware that " "while necessary locks to access objects and their labels are generally held, " "sufficient locks to modify an object or its label may not be present for all " "entry points. Locking information for arguments is documented in the MAC " "framework entry point document." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:5076 msgid "" "Policy entry points will pass a reference to the object label along with the " "object itself. This permits labeled policies to be unaware of the internals " "of the object yet still make decisions based on the label. The exception to " "this is the process credential, which is assumed to be understood by " "policies as a first class security object in the kernel." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:5087 msgid "MAC Policy Entry Point Reference" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:5090 msgid "General-Purpose Module Entry Points" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5093 msgid "mpo_init" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5096 msgid "" "void mpo_init struct " "mac_policy_conf *conf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5114 book.translate.xml:5160 book.translate.xml:5203 #: book.translate.xml:5271 book.translate.xml:5335 book.translate.xml:5377 #: book.translate.xml:5419 book.translate.xml:5461 book.translate.xml:5504 #: book.translate.xml:5562 book.translate.xml:5622 book.translate.xml:5671 #: book.translate.xml:5713 book.translate.xml:5756 book.translate.xml:5807 #: book.translate.xml:5857 book.translate.xml:5900 book.translate.xml:5942 #: book.translate.xml:5986 book.translate.xml:6030 book.translate.xml:6074 #: book.translate.xml:6118 book.translate.xml:6162 book.translate.xml:6206 #: book.translate.xml:6252 book.translate.xml:6302 book.translate.xml:6346 #: book.translate.xml:6390 book.translate.xml:6433 book.translate.xml:6476 #: book.translate.xml:6522 book.translate.xml:6571 book.translate.xml:6620 #: book.translate.xml:6671 book.translate.xml:6748 book.translate.xml:6825 #: book.translate.xml:6902 book.translate.xml:6978 book.translate.xml:7055 #: book.translate.xml:7132 book.translate.xml:7207 book.translate.xml:7282 #: book.translate.xml:7357 book.translate.xml:7432 book.translate.xml:7588 #: book.translate.xml:7667 book.translate.xml:7737 book.translate.xml:7800 #: book.translate.xml:7862 book.translate.xml:7929 book.translate.xml:8012 #: book.translate.xml:8101 book.translate.xml:8167 book.translate.xml:8216 #: book.translate.xml:8282 book.translate.xml:8349 book.translate.xml:8426 #: book.translate.xml:8492 book.translate.xml:8550 book.translate.xml:8611 #: book.translate.xml:8677 book.translate.xml:8742 book.translate.xml:8808 #: book.translate.xml:8873 book.translate.xml:8943 book.translate.xml:9001 #: book.translate.xml:9058 book.translate.xml:9124 book.translate.xml:9190 #: book.translate.xml:9256 book.translate.xml:9324 book.translate.xml:9392 #: book.translate.xml:9459 book.translate.xml:9528 book.translate.xml:9608 #: book.translate.xml:9677 book.translate.xml:9754 book.translate.xml:9821 #: book.translate.xml:9888 book.translate.xml:9944 book.translate.xml:10021 #: book.translate.xml:10084 book.translate.xml:10126 book.translate.xml:10170 #: book.translate.xml:10285 book.translate.xml:10349 book.translate.xml:10392 #: book.translate.xml:10441 book.translate.xml:10489 book.translate.xml:10540 #: book.translate.xml:10593 book.translate.xml:10636 book.translate.xml:10685 #: book.translate.xml:10752 book.translate.xml:10809 book.translate.xml:10868 #: book.translate.xml:10931 book.translate.xml:10989 book.translate.xml:11048 #: book.translate.xml:11110 book.translate.xml:11179 book.translate.xml:11237 #: book.translate.xml:11293 book.translate.xml:11354 book.translate.xml:11410 #: book.translate.xml:11475 book.translate.xml:11536 book.translate.xml:11591 #: book.translate.xml:11656 book.translate.xml:11721 book.translate.xml:11782 #: book.translate.xml:11852 book.translate.xml:11914 book.translate.xml:11976 #: book.translate.xml:12058 book.translate.xml:12145 book.translate.xml:12214 #: book.translate.xml:12279 book.translate.xml:12352 book.translate.xml:12438 #: book.translate.xml:12514 book.translate.xml:12578 book.translate.xml:12638 #: book.translate.xml:12697 book.translate.xml:12766 book.translate.xml:12848 #: book.translate.xml:12931 book.translate.xml:12991 book.translate.xml:13059 #: book.translate.xml:13122 book.translate.xml:13184 book.translate.xml:13250 #: book.translate.xml:13316 book.translate.xml:13394 book.translate.xml:13480 #: book.translate.xml:13548 book.translate.xml:13617 book.translate.xml:13689 #: book.translate.xml:13759 book.translate.xml:13816 book.translate.xml:13877 #: book.translate.xml:13945 book.translate.xml:14021 book.translate.xml:14094 #: book.translate.xml:14159 book.translate.xml:14213 book.translate.xml:14256 #: book.translate.xml:14304 book.translate.xml:14350 book.translate.xml:14411 msgid "Parameter" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5115 book.translate.xml:5161 book.translate.xml:5204 #: book.translate.xml:5272 book.translate.xml:5336 book.translate.xml:5378 #: book.translate.xml:5420 book.translate.xml:5462 book.translate.xml:5505 #: book.translate.xml:5563 book.translate.xml:5623 book.translate.xml:5672 #: book.translate.xml:5714 book.translate.xml:5757 book.translate.xml:5808 #: book.translate.xml:5858 book.translate.xml:5901 book.translate.xml:5943 #: book.translate.xml:5987 book.translate.xml:6031 book.translate.xml:6075 #: book.translate.xml:6119 book.translate.xml:6163 book.translate.xml:6207 #: book.translate.xml:6253 book.translate.xml:6303 book.translate.xml:6347 #: book.translate.xml:6391 book.translate.xml:6434 book.translate.xml:6477 #: book.translate.xml:6523 book.translate.xml:6572 book.translate.xml:6621 #: book.translate.xml:6672 book.translate.xml:6749 book.translate.xml:6826 #: book.translate.xml:6903 book.translate.xml:6979 book.translate.xml:7056 #: book.translate.xml:7133 book.translate.xml:7208 book.translate.xml:7283 #: book.translate.xml:7358 book.translate.xml:7433 book.translate.xml:7589 #: book.translate.xml:7668 book.translate.xml:7738 book.translate.xml:7801 #: book.translate.xml:7863 book.translate.xml:7930 book.translate.xml:8013 #: book.translate.xml:8102 book.translate.xml:8168 book.translate.xml:8217 #: book.translate.xml:8283 book.translate.xml:8350 book.translate.xml:8427 #: book.translate.xml:8493 book.translate.xml:8551 book.translate.xml:8612 #: book.translate.xml:8678 book.translate.xml:8743 book.translate.xml:8809 #: book.translate.xml:8874 book.translate.xml:8944 book.translate.xml:9002 #: book.translate.xml:9059 book.translate.xml:9125 book.translate.xml:9191 #: book.translate.xml:9257 book.translate.xml:9325 book.translate.xml:9393 #: book.translate.xml:9460 book.translate.xml:9529 book.translate.xml:9609 #: book.translate.xml:9678 book.translate.xml:9755 book.translate.xml:9822 #: book.translate.xml:9889 book.translate.xml:9945 book.translate.xml:10022 #: book.translate.xml:10085 book.translate.xml:10127 book.translate.xml:10171 #: book.translate.xml:10286 book.translate.xml:10350 book.translate.xml:10393 #: book.translate.xml:10442 book.translate.xml:10490 book.translate.xml:10541 #: book.translate.xml:10594 book.translate.xml:10637 book.translate.xml:10686 #: book.translate.xml:10753 book.translate.xml:10810 book.translate.xml:10869 #: book.translate.xml:10932 book.translate.xml:10990 book.translate.xml:11049 #: book.translate.xml:11111 book.translate.xml:11180 book.translate.xml:11238 #: book.translate.xml:11294 book.translate.xml:11355 book.translate.xml:11411 #: book.translate.xml:11476 book.translate.xml:11537 book.translate.xml:11592 #: book.translate.xml:11657 book.translate.xml:11722 book.translate.xml:11783 #: book.translate.xml:11853 book.translate.xml:11915 book.translate.xml:11977 #: book.translate.xml:12059 book.translate.xml:12146 book.translate.xml:12215 #: book.translate.xml:12280 book.translate.xml:12353 book.translate.xml:12439 #: book.translate.xml:12515 book.translate.xml:12579 book.translate.xml:12639 #: book.translate.xml:12698 book.translate.xml:12767 book.translate.xml:12849 #: book.translate.xml:12932 book.translate.xml:12992 book.translate.xml:13060 #: book.translate.xml:13123 book.translate.xml:13185 book.translate.xml:13251 #: book.translate.xml:13317 book.translate.xml:13395 book.translate.xml:13481 #: book.translate.xml:13549 book.translate.xml:13618 book.translate.xml:13690 #: book.translate.xml:13760 book.translate.xml:13817 book.translate.xml:13878 #: book.translate.xml:13946 book.translate.xml:14022 book.translate.xml:14095 #: book.translate.xml:14160 book.translate.xml:14214 book.translate.xml:14257 #: book.translate.xml:14305 book.translate.xml:14351 book.translate.xml:14412 msgid "Description" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5116 book.translate.xml:5162 book.translate.xml:5205 #: book.translate.xml:5273 book.translate.xml:5337 book.translate.xml:5379 #: book.translate.xml:5421 book.translate.xml:5463 book.translate.xml:5506 #: book.translate.xml:5564 book.translate.xml:5624 book.translate.xml:5673 #: book.translate.xml:5715 book.translate.xml:5758 book.translate.xml:5809 #: book.translate.xml:5859 book.translate.xml:5902 book.translate.xml:5944 #: book.translate.xml:5988 book.translate.xml:6032 book.translate.xml:6076 #: book.translate.xml:6120 book.translate.xml:6164 book.translate.xml:6208 #: book.translate.xml:6254 book.translate.xml:6304 book.translate.xml:6348 #: book.translate.xml:6392 book.translate.xml:6435 book.translate.xml:6478 #: book.translate.xml:6524 book.translate.xml:6573 book.translate.xml:6622 #: book.translate.xml:6673 book.translate.xml:6750 book.translate.xml:6827 #: book.translate.xml:6904 book.translate.xml:6980 book.translate.xml:7057 #: book.translate.xml:7134 book.translate.xml:7209 book.translate.xml:7284 #: book.translate.xml:7359 book.translate.xml:7434 book.translate.xml:7590 #: book.translate.xml:7669 book.translate.xml:7739 book.translate.xml:7802 #: book.translate.xml:7864 book.translate.xml:7931 book.translate.xml:8014 #: book.translate.xml:8103 book.translate.xml:8169 book.translate.xml:8218 #: book.translate.xml:8284 book.translate.xml:8351 book.translate.xml:8428 #: book.translate.xml:8494 book.translate.xml:8552 book.translate.xml:8613 #: book.translate.xml:8679 book.translate.xml:8744 book.translate.xml:8810 #: book.translate.xml:8875 book.translate.xml:8945 book.translate.xml:9003 #: book.translate.xml:9060 book.translate.xml:9126 book.translate.xml:9192 #: book.translate.xml:9258 book.translate.xml:9326 book.translate.xml:9394 #: book.translate.xml:9461 book.translate.xml:9530 book.translate.xml:9610 #: book.translate.xml:9679 book.translate.xml:9756 book.translate.xml:9823 #: book.translate.xml:9890 book.translate.xml:9946 book.translate.xml:10023 #: book.translate.xml:10086 book.translate.xml:10128 book.translate.xml:10172 #: book.translate.xml:10287 book.translate.xml:10351 book.translate.xml:10394 #: book.translate.xml:10443 book.translate.xml:10491 book.translate.xml:10542 #: book.translate.xml:10595 book.translate.xml:10638 book.translate.xml:10687 #: book.translate.xml:10754 book.translate.xml:10811 book.translate.xml:10870 #: book.translate.xml:10933 book.translate.xml:10991 book.translate.xml:11050 #: book.translate.xml:11112 book.translate.xml:11181 book.translate.xml:11239 #: book.translate.xml:11295 book.translate.xml:11356 book.translate.xml:11412 #: book.translate.xml:11477 book.translate.xml:11538 book.translate.xml:11593 #: book.translate.xml:11658 book.translate.xml:11723 book.translate.xml:11784 #: book.translate.xml:11854 book.translate.xml:11916 book.translate.xml:11978 #: book.translate.xml:12060 book.translate.xml:12147 book.translate.xml:12216 #: book.translate.xml:12281 book.translate.xml:12354 book.translate.xml:12440 #: book.translate.xml:12516 book.translate.xml:12580 book.translate.xml:12640 #: book.translate.xml:12699 book.translate.xml:12768 book.translate.xml:12850 #: book.translate.xml:12933 book.translate.xml:12993 book.translate.xml:13061 #: book.translate.xml:13124 book.translate.xml:13186 book.translate.xml:13252 #: book.translate.xml:13318 book.translate.xml:13396 book.translate.xml:13482 #: book.translate.xml:13550 book.translate.xml:13619 book.translate.xml:13691 #: book.translate.xml:13761 book.translate.xml:13818 book.translate.xml:13879 #: book.translate.xml:13947 book.translate.xml:14023 book.translate.xml:14096 #: book.translate.xml:14161 book.translate.xml:14215 book.translate.xml:14258 #: book.translate.xml:14306 book.translate.xml:14352 book.translate.xml:14413 msgid "Locking" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5123 book.translate.xml:5169 msgid "conf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5124 book.translate.xml:5170 msgid "MAC policy definition" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5130 msgid "" "Policy load event. The policy list mutex is held, so sleep operations cannot " "be performed, and calls out to other kernel subsystems must be made with " "caution. If potentially sleeping memory allocations are required during " "policy initialization, they should be made using a separate module SYSINIT()." "" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5139 msgid "mpo_destroy" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5142 msgid "" "void mpo_destroy struct " "mac_policy_conf *conf" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5176 msgid "" "Policy load event. The policy list mutex is held, so caution should be " "applied." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5181 msgid "mpo_syscall" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5184 msgid "" "int mpo_syscall struct " "thread *td int call void *arg" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5212 book.translate.xml:5280 msgid "td" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5213 msgid "Calling thread" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5217 msgid "call" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5218 msgid "Policy-specific syscall number" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5222 msgid "arg" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5223 msgid "Pointer to syscall arguments" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5229 msgid "" "This entry point provides a policy-multiplexed system call so that policies " "may provide additional services to user processes without registering " "specific system calls. The policy name provided during registration is used " "to demux calls from userland, and the arguments will be forwarded to this " "entry point. When implementing new services, security modules should be sure " "to invoke appropriate access control checks from the MAC framework as needed." " For example, if a policy implements an augmented signal functionality, it " "should call the necessary signal access control checks to invoke the MAC " "framework and other registered policies." msgstr "" #. (itstool) path: note/para #: book.translate.xml:5243 msgid "" "Modules must currently perform the copyin() of the " "syscall data on their own." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5250 msgid "mpo_thread_userret" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5253 msgid "" "void mpo_thread_userret " "struct thread *td" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5281 msgid "Returning thread" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5288 msgid "" "This entry point permits policy modules to perform MAC-related events when a " "thread returns to user space, via a system call return, trap return, or " "otherwise. This is required for policies that have floating process labels, " "as it is not always possible to acquire the process lock at arbitrary points " "in the stack during system call processing; process labels might represent " "traditional authentication data, process history information, or other data. " "To employ this mechanism, intended changes to the process credential label " "may be stored in the p_label protected by a per-policy " "spin lock, and then set the per-thread TDF_ASTPENDING " "flag and per-process PS_MACPENDM flag to schedule a call " "to the userret entry point. From this entry point, the policy may create a " "replacement credential with less concern about the locking context. Policy " "writers are cautioned that event ordering relating to scheduling an AST and " "the AST being performed may be complex and interlaced in multithreaded " "applications." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:5311 msgid "Label Operations" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5314 msgid "mpo_init_bpfdesc_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5317 msgid "" "void mpo_init_bpfdesc_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5344 book.translate.xml:5386 book.translate.xml:5428 #: book.translate.xml:5470 book.translate.xml:5513 book.translate.xml:5577 #: book.translate.xml:5680 book.translate.xml:5722 book.translate.xml:5765 #: book.translate.xml:5816 book.translate.xml:5866 book.translate.xml:5909 #: book.translate.xml:5951 book.translate.xml:5995 book.translate.xml:6039 #: book.translate.xml:6083 book.translate.xml:6127 book.translate.xml:6171 #: book.translate.xml:6215 book.translate.xml:6311 book.translate.xml:6399 #: book.translate.xml:6442 book.translate.xml:6485 book.translate.xml:6681 #: book.translate.xml:6758 book.translate.xml:6835 book.translate.xml:6912 #: book.translate.xml:6988 book.translate.xml:7065 book.translate.xml:7142 #: book.translate.xml:7217 book.translate.xml:7292 book.translate.xml:7367 #: book.translate.xml:7442 book.translate.xml:7820 book.translate.xml:8031 #: book.translate.xml:11801 book.translate.xml:12088 book.translate.xml:12166 #: book.translate.xml:12233 book.translate.xml:12298 book.translate.xml:12371 #: book.translate.xml:12468 book.translate.xml:12533 book.translate.xml:12596 #: book.translate.xml:12722 book.translate.xml:12796 book.translate.xml:12878 #: book.translate.xml:13078 book.translate.xml:13203 book.translate.xml:13269 #: book.translate.xml:13335 book.translate.xml:13413 book.translate.xml:13499 #: book.translate.xml:13567 book.translate.xml:13636 book.translate.xml:13708 #: book.translate.xml:13896 msgid "label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5345 book.translate.xml:5429 book.translate.xml:5471 #: book.translate.xml:5514 msgid "New label to apply" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5351 msgid "" "Initialize the label on a newly instantiated bpfdesc (BPF descriptor). " "Sleeping is permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5356 msgid "mpo_init_cred_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5359 msgid "" "void mpo_init_cred_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5387 book.translate.xml:5766 book.translate.xml:5817 #: book.translate.xml:5867 book.translate.xml:5910 msgid "New label to initialize" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5393 msgid "" "Initialize the label for a newly instantiated user credential. Sleeping is " "permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5398 msgid "mpo_init_devfsdirent_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5401 msgid "" "void mpo_init_devfsdirent_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5435 msgid "" "Initialize the label on a newly instantiated devfs entry. Sleeping is " "permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5440 msgid "mpo_init_ifnet_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5443 msgid "" "void mpo_init_ifnet_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5477 msgid "" "Initialize the label on a newly instantiated network interface. Sleeping is " "permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5482 msgid "mpo_init_ipq_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5485 msgid "" "void mpo_init_ipq_label " "struct label *label " "int flag" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5518 book.translate.xml:5571 book.translate.xml:5770 #: book.translate.xml:5821 msgid "flag" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5519 book.translate.xml:5572 msgid "" "Sleeping/non-sleeping malloc9; see below" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5526 msgid "" "Initialize the label on a newly instantiated IP fragment reassembly queue. " "The flag field may be one of M_WAITOK and M_NOWAIT, and should be employed to avoid " "performing a sleeping malloc9 during this " "initialization call. IP fragment reassembly queue allocation frequently " "occurs in performance sensitive environments, and the implementation should " "be careful to avoid sleeping or long-lived operations. This entry point is " "permitted to fail resulting in the failure to allocate the IP fragment " "reassembly queue." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5540 msgid "mpo_init_mbuf_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5543 msgid "" "void mpo_init_mbuf_label " "int flag struct label " "*label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5578 msgid "Policy label to initialize" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5584 msgid "" "Initialize the label on a newly instantiated mbuf packet header " "(mbuf). The flag field may be " "one of M_WAITOK and M_NOWAIT, and should " "be employed to avoid performing a sleeping " "malloc9 during this initialization call. Mbuf allocation frequently " "occurs in performance sensitive environments, and the implementation should " "be careful to avoid sleeping or long-lived operations. This entry point is " "permitted to fail resulting in the failure to allocate the mbuf header." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5598 msgid "mpo_init_mount_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5601 msgid "" "void mpo_init_mount_label " "struct label *mntlabel " "struct label *fslabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5631 book.translate.xml:6261 book.translate.xml:8120 msgid "mntlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5632 msgid "Policy label to be initialized for the mount itself" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5637 book.translate.xml:6266 book.translate.xml:7602 #: book.translate.xml:7681 book.translate.xml:7751 book.translate.xml:8126 msgid "fslabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5638 msgid "Policy label to be initialized for the file system" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5645 msgid "" "Initialize the labels on a newly instantiated mount point. Sleeping is " "permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5650 msgid "mpo_init_mount_fs_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5653 msgid "" "void mpo_init_mount_fs_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5681 msgid "Label to be initialized" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5687 msgid "" "Initialize the label on a newly mounted file system. Sleeping is permitted" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5692 msgid "mpo_init_pipe_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5695 msgid "" "void mpo_init_pipe_label " "struct label*label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5723 book.translate.xml:7143 book.translate.xml:7218 #: book.translate.xml:7293 book.translate.xml:7368 book.translate.xml:7443 msgid "Label to be filled in" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5729 msgid "" "Initialize a label for a newly instantiated pipe. Sleeping is permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5734 msgid "mpo_init_socket_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5737 msgid "" "void mpo_init_socket_label " "struct label *label " "int flag" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5771 book.translate.xml:5822 msgid "" "malloc9 flags" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5777 msgid "" "Initialize a label for a newly instantiated socket. The flag field may be one of M_WAITOK and " "M_NOWAIT, and should be employed to avoid performing a " "sleeping malloc9 during this initialization call." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5785 msgid "mpo_init_socket_peer_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5788 msgid "" "void mpo_init_socket_peer_label " "struct label *label " "int flag" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5828 msgid "" "Initialize the peer label for a newly instantiated socket. The " "flag field may be one of M_WAITOK " "and M_NOWAIT, and should be employed to avoid performing a " "sleeping malloc9 during this initialization call." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5836 msgid "mpo_init_proc_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5839 msgid "" "void mpo_init_proc_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5873 msgid "" "Initialize the label for a newly instantiated process. Sleeping is permitted." "" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5879 msgid "mpo_init_vnode_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5882 msgid "" "void mpo_init_vnode_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5916 msgid "" "Initialize the label on a newly instantiated vnode. Sleeping is permitted." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5921 msgid "mpo_destroy_bpfdesc_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5924 msgid "" "void mpo_destroy_bpfdesc_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5952 msgid "bpfdesc label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:5958 msgid "" "Destroy the label on a BPF descriptor. In this entry point a policy should " "free any internal storage associated with label so " "that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:5965 msgid "mpo_destroy_cred_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:5968 msgid "" "void mpo_destroy_cred_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:5996 book.translate.xml:6040 book.translate.xml:6084 #: book.translate.xml:6128 book.translate.xml:6172 msgid "Label being destroyed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6002 msgid "" "Destroy the label on a credential. In this entry point, a policy module " "should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6009 msgid "mpo_destroy_devfsdirent_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6012 msgid "" "void mpo_destroy_devfsdirent_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6046 msgid "" "Destroy the label on a devfs entry. In this entry point, a policy module " "should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6053 msgid "mpo_destroy_ifnet_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6056 msgid "" "void mpo_destroy_ifnet_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6090 msgid "" "Destroy the label on a removed interface. In this entry point, a policy " "module should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6097 msgid "mpo_destroy_ipq_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6100 msgid "" "void mpo_destroy_ipq_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6134 msgid "" "Destroy the label on an IP fragment queue. In this entry point, a policy " "module should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6141 msgid "mpo_destroy_mbuf_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6144 msgid "" "void mpo_destroy_mbuf_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6178 msgid "" "Destroy the label on an mbuf header. In this entry point, a policy module " "should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6185 book.translate.xml:6229 msgid "mpo_destroy_mount_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6188 msgid "" "void mpo_destroy_mount_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6216 book.translate.xml:6262 msgid "Mount point label being destroyed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6222 msgid "" "Destroy the labels on a mount point. In this entry point, a policy module " "should free the internal storage associated with mntlabel so that they may be destroyed." msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6232 msgid "" "void mpo_destroy_mount_label " "struct label *mntlabel " "struct label *fslabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6267 msgid "File system label being destroyed>" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6273 msgid "" "Destroy the labels on a mount point. In this entry point, a policy module " "should free the internal storage associated with mntlabel and fslabel so that they may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6281 msgid "mpo_destroy_socket_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6284 msgid "" "void mpo_destroy_socket_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6312 msgid "Socket label being destroyed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6318 msgid "" "Destroy the label on a socket. In this entry point, a policy module should " "free any internal storage associated with label so " "that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6325 msgid "mpo_destroy_socket_peer_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6328 msgid "" "void mpo_destroy_socket_peer_label " "struct label *peerlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6355 msgid "peerlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6356 msgid "Socket peer label being destroyed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6362 msgid "" "Destroy the peer label on a socket. In this entry point, a policy module " "should free any internal storage associated with label so that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6369 msgid "mpo_destroy_pipe_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6372 msgid "" "void mpo_destroy_pipe_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6400 msgid "Pipe label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6406 msgid "" "Destroy the label on a pipe. In this entry point, a policy module should " "free any internal storage associated with label so " "that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6413 msgid "mpo_destroy_proc_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6416 msgid "" "void mpo_destroy_proc_label " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6443 book.translate.xml:6486 msgid "Process label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6449 msgid "" "Destroy the label on a process. In this entry point, a policy module should " "free any internal storage associated with label so " "that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6456 msgid "mpo_destroy_vnode_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6459 msgid "" "void mpo_destroy_vnode_label " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6492 msgid "" "Destroy the label on a vnode. In this entry point, a policy module should " "free any internal storage associated with label so " "that it may be destroyed." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6499 msgid "mpo_copy_mbuf_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6502 msgid "" "void mpo_copy_mbuf_label " "struct label *src " "struct label *dest" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6531 book.translate.xml:6580 book.translate.xml:6629 msgid "src" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6532 book.translate.xml:6581 book.translate.xml:6630 msgid "Source label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6536 book.translate.xml:6585 book.translate.xml:6634 msgid "dest" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6537 book.translate.xml:6586 book.translate.xml:6635 msgid "Destination label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6543 book.translate.xml:6592 book.translate.xml:6641 msgid "" "Copy the label information in src into " "dest." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6548 msgid "mpo_copy_pipe_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6551 msgid "" "void mpo_copy_pipe_label " "struct label *src " "struct label *dest" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6597 msgid "mpo_copy_vnode_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6600 msgid "" "void mpo_copy_vnode_label " "struct label *src " "struct label *dest" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6646 msgid "mpo_externalize_cred_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6649 msgid "" "int mpo_externalize_cred_label " "struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6682 book.translate.xml:6759 book.translate.xml:6836 #: book.translate.xml:6913 book.translate.xml:6989 book.translate.xml:7066 msgid "Label to be externalized" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6686 book.translate.xml:6763 book.translate.xml:6840 #: book.translate.xml:6917 book.translate.xml:6993 book.translate.xml:7070 #: book.translate.xml:7147 book.translate.xml:7222 book.translate.xml:7297 #: book.translate.xml:7372 book.translate.xml:7447 msgid "element_name" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6687 book.translate.xml:6764 book.translate.xml:6841 #: book.translate.xml:6918 book.translate.xml:6994 book.translate.xml:7071 msgid "Name of the policy whose label should be externalized" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6691 book.translate.xml:6768 book.translate.xml:6845 #: book.translate.xml:6922 book.translate.xml:6998 book.translate.xml:7075 msgid "sb" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6692 book.translate.xml:6769 book.translate.xml:6846 #: book.translate.xml:6923 book.translate.xml:6999 book.translate.xml:7076 msgid "String buffer to be filled with a text representation of label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6697 book.translate.xml:6774 book.translate.xml:6851 #: book.translate.xml:6928 book.translate.xml:7004 book.translate.xml:7081 #: book.translate.xml:7157 book.translate.xml:7232 book.translate.xml:7307 #: book.translate.xml:7382 book.translate.xml:7457 msgid "claimed" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:6698 book.translate.xml:6775 book.translate.xml:6852 #: book.translate.xml:6929 book.translate.xml:7005 book.translate.xml:7082 msgid "" "Should be incremented when element_data can be filled " "in." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:6707 book.translate.xml:6784 book.translate.xml:6861 #: book.translate.xml:6938 book.translate.xml:7014 book.translate.xml:7091 msgid "" "Produce an externalized label based on the label structure passed. An " "externalized label consists of a text representation of the label contents " "that can be used with userland applications and read by the user. Currently, " "all policies' externalize entry points will be called, " "so the implementation should check the contents of element_name before attempting to fill in sb. If " "element_name does not match the name of your policy, " "simply return 0. Only return nonzero if an error " "occurs while externalizing the label data. Once the policy fills in " "element_data, *claimed should be " "incremented." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6723 msgid "mpo_externalize_ifnet_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6726 msgid "" "int mpo_externalize_ifnet_label " "struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6800 msgid "mpo_externalize_pipe_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6803 msgid "" "int mpo_externalize_pipe_label " "struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6877 msgid "mpo_externalize_socket_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6880 msgid "" "int mpo_externalize_socket_label " "struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:6954 msgid "mpo_externalize_socket_peer_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:6957 msgid "" "int mpo_externalize_socket_peer_label struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7030 msgid "mpo_externalize_vnode_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7033 msgid "" "int mpo_externalize_vnode_label " "struct label *label " "char *element_name " "struct sbuf *sb int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7107 msgid "mpo_internalize_cred_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7110 msgid "" "int mpo_internalize_cred_label " "struct label *label " "char *element_name " "char *element_data int " "*claimed" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7148 book.translate.xml:7223 book.translate.xml:7298 #: book.translate.xml:7373 book.translate.xml:7448 msgid "Name of the policy whose label should be internalized" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7152 book.translate.xml:7227 book.translate.xml:7302 #: book.translate.xml:7377 book.translate.xml:7452 msgid "element_data" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7153 book.translate.xml:7228 book.translate.xml:7303 #: book.translate.xml:7378 book.translate.xml:7453 msgid "Text data to be internalized" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7158 book.translate.xml:7233 book.translate.xml:7308 #: book.translate.xml:7383 book.translate.xml:7458 msgid "Should be incremented when data can be successfully internalized." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:7167 book.translate.xml:7242 book.translate.xml:7317 #: book.translate.xml:7392 book.translate.xml:7467 msgid "" "Produce an internal label structure based on externalized label data in text " "format. Currently, all policies' internalize entry " "points are called when internalization is requested, so the implementation " "should compare the contents of element_name to its " "own name in order to be sure it should be internalizing the data in " "element_data. Just as in the externalize entry points, the entry point should return 0 if element_name does not match its own " "name, or when data can successfully be internalized, in which case " "*claimed should be incremented." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7182 msgid "mpo_internalize_ifnet_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7185 msgid "" "int mpo_internalize_ifnet_label " "struct label *label " "char *element_name " "char *element_data int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7257 msgid "mpo_internalize_pipe_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7260 msgid "" "int mpo_internalize_pipe_label " "struct label *label " "char *element_name " "char *element_data int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7332 msgid "mpo_internalize_socket_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7335 msgid "" "int mpo_internalize_socket_label " "struct label *label " "char *element_name " "char *element_data int " "*claimed" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7407 msgid "mpo_internalize_vnode_label" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7410 msgid "" "int mpo_internalize_vnode_label " "struct label *label " "char *element_name " "char *element_data int " "*claimed" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:7483 msgid "Label Events" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7485 msgid "" "This class of entry points is used by the MAC framework to permit policies " "to maintain label information on kernel objects. For each labeled kernel " "object of interest to a MAC policy, entry points may be registered for " "relevant life cycle events. All objects implement initialization, creation, " "and destruction hooks. Some objects will also implement relabeling, allowing " "user processes to change the labels on objects. Some objects will also " "implement object-specific events, such as label events associated with IP " "reassembly. A typical labeled object will have the following life cycle of " "entry points:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:7497 #, no-wrap msgid "" "Label initialization o\n" "(object-specific wait) \\\n" "Label creation o\n" " \\\n" "Relabel events, o--<--.\n" "Various object-specific, | |\n" "Access control events ~-->--o\n" " \\\n" "Label destruction o" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7507 msgid "" "Label initialization permits policies to allocate memory and set initial " "values for labels without context for the use of the object. The label slot " "allocated to a policy will be zeroed by default, so some policies may not " "need to perform initialization." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7513 msgid "" "Label creation occurs when the kernel structure is associated with an actual " "kernel object. For example, Mbufs may be allocated and remain unused in a " "pool until they are required. mbuf allocation causes label initialization on " "the mbuf to take place, but mbuf creation occurs when the mbuf is associated " "with a datagram. Typically, context will be provided for a creation event, " "including the circumstances of the creation, and labels of other relevant " "objects in the creation process. For example, when an mbuf is created from a " "socket, the socket and its label will be presented to registered policies in " "addition to the new mbuf and its label. Memory allocation in creation events " "is discouraged, as it may occur in performance sensitive ports of the " "kernel; in addition, creation calls are not permitted to fail so a failure " "to allocate memory cannot be reported." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7529 msgid "" "Object specific events do not generally fall into the other broad classes of " "label events, but will generally provide an opportunity to modify or update " "the label on an object based on additional context. For example, the label " "on an IP fragment reassembly queue may be updated during the " "MAC_UPDATE_IPQ entry point as a result of the acceptance of " "an additional mbuf to that queue." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7537 msgid "" "Access control events are discussed in detail in the following section." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7540 msgid "" "Label destruction permits policies to release storage or state associated " "with a label during its association with an object so that the kernel data " "structures supporting the object may be reused or released." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:7545 msgid "" "In addition to labels associated with specific kernel objects, an additional " "class of labels exists: temporary labels. These labels are used to store " "update information submitted by user processes. These labels are initialized " "and destroyed as with other label types, but the creation event is " "MAC_INTERNALIZE, which accepts a user label to be converted " "to an in-kernel representation." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:7554 msgid "File System Object Labeling Event Operations" msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7557 msgid "mpo_associate_vnode_devfs" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7560 msgid "" "void mpo_associate_vnode_devfs " "struct mount *mp " "struct label *fslabel " "struct devfs_dirent *de " "struct label *delabel " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7597 book.translate.xml:7676 book.translate.xml:7746 #: book.translate.xml:7943 book.translate.xml:8115 book.translate.xml:11670 msgid "mp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7598 book.translate.xml:7944 msgid "Devfs mount point" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7603 msgid "Devfs file system label (mp->mnt_fslabel)" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7608 book.translate.xml:7959 msgid "de" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7609 msgid "Devfs directory entry" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7613 book.translate.xml:7964 msgid "delabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7614 msgid "Policy label associated with de" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7619 book.translate.xml:7686 book.translate.xml:7756 #: book.translate.xml:8047 book.translate.xml:8230 book.translate.xml:8296 #: book.translate.xml:8370 book.translate.xml:9964 book.translate.xml:10037 #: book.translate.xml:10554 book.translate.xml:11606 book.translate.xml:11796 #: book.translate.xml:12083 book.translate.xml:12160 book.translate.xml:12228 #: book.translate.xml:12293 book.translate.xml:12366 book.translate.xml:12463 #: book.translate.xml:12528 book.translate.xml:12592 book.translate.xml:12652 #: book.translate.xml:12717 book.translate.xml:12791 book.translate.xml:12873 #: book.translate.xml:13073 book.translate.xml:13198 book.translate.xml:13264 #: book.translate.xml:13330 book.translate.xml:13408 book.translate.xml:13494 #: book.translate.xml:13562 book.translate.xml:13631 book.translate.xml:13703 #: book.translate.xml:13891 book.translate.xml:14173 book.translate.xml:14364 msgid "vp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7620 msgid "vnode associated with de" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7625 book.translate.xml:7691 book.translate.xml:7761 #: book.translate.xml:8052 book.translate.xml:8302 book.translate.xml:10559 #: book.translate.xml:14178 book.translate.xml:14369 msgid "vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7626 book.translate.xml:7692 book.translate.xml:7762 #: book.translate.xml:8053 book.translate.xml:8303 book.translate.xml:12469 #: book.translate.xml:12534 book.translate.xml:12723 book.translate.xml:12797 #: book.translate.xml:12879 msgid "Policy label associated with vp" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7633 msgid "" "Fill in the label (vlabel) for a newly created devfs " "vnode based on the devfs directory entry passed in de " "and its label." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7640 msgid "mpo_associate_vnode_extattr" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7643 msgid "" "int mpo_associate_vnode_extattr " "struct mount *mp " "struct label *fslabel " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7677 book.translate.xml:7747 book.translate.xml:8027 msgid "File system mount point" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7682 book.translate.xml:7752 book.translate.xml:8032 msgid "File system label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7687 book.translate.xml:7757 msgid "Vnode to label" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7699 msgid "" "Attempt to retrieve the label for vp from the file " "system extended attributes. Upon success, the value 0 is " "returned. Should extended attribute retrieval not be supported, an accepted " "fallback is to copy fslabel into vlabel. In the event of an error, an appropriate value for " "errno should be returned." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7711 msgid "mpo_associate_vnode_singlelabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7714 msgid "" "void mpo_associate_vnode_singlelabel " "struct mount *mp " "struct label *fslabel " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7769 msgid "" "On non-multilabel file systems, this entry point is called to set the policy " "label for vp based on the file system label, " "fslabel." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7776 msgid "mpo_create_devfs_device" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7779 msgid "" "void mpo_create_devfs_device " "dev_t dev struct " "devfs_dirent *devfs_dirent " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7809 msgid "dev" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7810 msgid "Device corresponding with devfs_dirent" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7815 book.translate.xml:7882 book.translate.xml:8358 msgid "devfs_dirent" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7816 msgid "Devfs directory entry to be labeled." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7821 msgid "Label for devfs_dirent to be filled in." msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7828 msgid "" "Fill out the label on a devfs_dirent being created for the passed device. " "This call will be made when the device file system is mounted, regenerated, " "or a new device is made available." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7835 msgid "mpo_create_devfs_directory" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7838 msgid "" "void mpo_create_devfs_directory " "char *dirname int " "dirnamelen struct devfs_dirent " "*devfs_dirent struct label " "*label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7871 msgid "dirname" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7872 msgid "Name of directory being created" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7876 book.translate.xml:14430 msgid "namelen" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7877 msgid "Length of string dirname" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7883 msgid "Devfs directory entry for directory being created." msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7890 msgid "" "Fill out the label on a devfs_dirent being created for the passed directory. " "This call will be made when the device file system is mounted, regenerated, " "or a new device requiring a specific directory hierarchy is made available." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7898 msgid "mpo_create_devfs_symlink" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7901 msgid "" "void mpo_create_devfs_symlink " "struct ucred *cred " "struct mount *mp " "struct devfs_dirent *dd " "struct label *ddlabel " "struct devfs_dirent *de " "struct label *delabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7938 book.translate.xml:8021 book.translate.xml:8110 #: book.translate.xml:8225 book.translate.xml:8291 book.translate.xml:8501 #: book.translate.xml:8559 book.translate.xml:8686 book.translate.xml:8751 #: book.translate.xml:8952 book.translate.xml:9763 book.translate.xml:10093 #: book.translate.xml:10135 book.translate.xml:10179 book.translate.xml:10358 #: book.translate.xml:10401 book.translate.xml:10450 book.translate.xml:10498 #: book.translate.xml:10549 book.translate.xml:10602 book.translate.xml:10645 #: book.translate.xml:10694 book.translate.xml:10761 book.translate.xml:10818 #: book.translate.xml:10877 book.translate.xml:10940 book.translate.xml:10998 #: book.translate.xml:11057 book.translate.xml:11119 book.translate.xml:11188 #: book.translate.xml:11246 book.translate.xml:11363 book.translate.xml:11419 #: book.translate.xml:11484 book.translate.xml:11545 book.translate.xml:11600 #: book.translate.xml:11665 book.translate.xml:11730 book.translate.xml:11791 #: book.translate.xml:11861 book.translate.xml:11923 book.translate.xml:11985 #: book.translate.xml:12067 book.translate.xml:12154 book.translate.xml:12223 #: book.translate.xml:12288 book.translate.xml:12361 book.translate.xml:12447 #: book.translate.xml:12523 book.translate.xml:12587 book.translate.xml:12647 #: book.translate.xml:12775 book.translate.xml:12857 book.translate.xml:12940 #: book.translate.xml:13000 book.translate.xml:13068 book.translate.xml:13131 #: book.translate.xml:13193 book.translate.xml:13259 book.translate.xml:13325 #: book.translate.xml:13403 book.translate.xml:13489 book.translate.xml:13557 #: book.translate.xml:13626 book.translate.xml:13698 book.translate.xml:13768 #: book.translate.xml:13825 book.translate.xml:13886 book.translate.xml:13954 #: book.translate.xml:14030 book.translate.xml:14103 book.translate.xml:14222 #: book.translate.xml:14265 book.translate.xml:14313 book.translate.xml:14359 #: book.translate.xml:14420 msgid "cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7939 book.translate.xml:8022 book.translate.xml:8111 #: book.translate.xml:8226 book.translate.xml:8292 book.translate.xml:8502 #: book.translate.xml:8560 book.translate.xml:8687 book.translate.xml:8752 #: book.translate.xml:8953 book.translate.xml:9764 book.translate.xml:10180 #: book.translate.xml:10359 book.translate.xml:10402 book.translate.xml:10451 #: book.translate.xml:10499 book.translate.xml:10550 book.translate.xml:10603 #: book.translate.xml:10646 book.translate.xml:10695 book.translate.xml:10762 #: book.translate.xml:10819 book.translate.xml:10878 book.translate.xml:10941 #: book.translate.xml:10999 book.translate.xml:11058 book.translate.xml:11120 #: book.translate.xml:11189 book.translate.xml:11247 book.translate.xml:11303 #: book.translate.xml:11364 book.translate.xml:11420 book.translate.xml:11485 #: book.translate.xml:11546 book.translate.xml:11601 book.translate.xml:11666 #: book.translate.xml:11731 book.translate.xml:11792 book.translate.xml:11862 #: book.translate.xml:11924 book.translate.xml:11986 book.translate.xml:12068 #: book.translate.xml:12155 book.translate.xml:12224 book.translate.xml:12289 #: book.translate.xml:12362 book.translate.xml:12448 book.translate.xml:12524 #: book.translate.xml:12648 book.translate.xml:12707 book.translate.xml:12776 #: book.translate.xml:12858 book.translate.xml:12941 book.translate.xml:13001 #: book.translate.xml:13069 book.translate.xml:13132 book.translate.xml:13194 #: book.translate.xml:13260 book.translate.xml:13326 book.translate.xml:13404 #: book.translate.xml:13490 book.translate.xml:13558 book.translate.xml:13627 #: book.translate.xml:13699 book.translate.xml:13769 book.translate.xml:13826 #: book.translate.xml:13887 book.translate.xml:13955 book.translate.xml:14031 #: book.translate.xml:14104 book.translate.xml:14169 book.translate.xml:14223 #: book.translate.xml:14266 book.translate.xml:14314 book.translate.xml:14360 #: book.translate.xml:14421 msgid "Subject credential" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7948 msgid "dd" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7949 msgid "Link destination" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7953 msgid "ddlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7954 msgid "Label associated with dd" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7960 msgid "Symlink entry" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:7965 msgid "Label associated with de" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:7972 msgid "" "Fill in the label (delabel) for a newly created " "devfs5 symbolic link entry." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:7977 msgid "mpo_create_vnode_extattr" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:7980 msgid "" "int mpo_create_vnode_extattr " "struct ucred *cred " "struct mount *mp " "struct label *fslabel " "struct vnode *dvp " "struct label *dlabel " "struct vnode *vp " "struct label *vlabel " "struct componentname *cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8026 msgid "mount" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8036 book.translate.xml:11866 book.translate.xml:11928 #: book.translate.xml:11990 book.translate.xml:12072 book.translate.xml:12452 #: book.translate.xml:12780 book.translate.xml:12862 book.translate.xml:13005 #: book.translate.xml:13136 msgid "dvp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8037 book.translate.xml:12073 msgid "Parent directory vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8041 book.translate.xml:11871 book.translate.xml:11933 #: book.translate.xml:11995 book.translate.xml:12077 book.translate.xml:12457 #: book.translate.xml:12785 book.translate.xml:12867 book.translate.xml:13010 #: book.translate.xml:13141 msgid "dlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8042 msgid "Label associated with dvp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8048 msgid "Newly created vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8058 book.translate.xml:12001 book.translate.xml:12094 #: book.translate.xml:12474 book.translate.xml:12802 book.translate.xml:12890 #: book.translate.xml:13016 msgid "cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8059 book.translate.xml:12095 book.translate.xml:12803 msgid "Component name for vp" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8066 msgid "" "Write out the label for vp to the appropriate " "extended attribute. If the write succeeds, fill in vlabel with the label, and return 0. " "Otherwise, return an appropriate error." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8074 msgid "mpo_create_mount" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8077 msgid "" "void mpo_create_mount " "struct ucred *cred " "struct mount *mp " "struct label *mnt " "struct label *fslabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8116 msgid "Object; file system being mounted" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8121 msgid "Policy label to be filled in for mp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8127 msgid "Policy label for the file system mp mounts." msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8134 msgid "" "Fill out the labels on the mount point being created by the passed subject " "credential. This call will be made when a new file system is mounted." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8140 msgid "mpo_create_root_mount" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8143 msgid "" "void mpo_create_root_mount " "struct ucred *cred " "struct mount *mp " "struct label *mntlabel " "struct label *fslabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8176 msgid "See ." msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8182 msgid "" "Fill out the labels on the mount point being created by the passed subject " "credential. This call will be made when the root file system is mounted, " "after mpo_create_mount;." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8189 msgid "mpo_relabel_vnode" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8192 msgid "" "void mpo_relabel_vnode " "struct ucred *cred " "struct vnode *vp " "struct label *vnodelabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8231 msgid "vnode to relabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8235 book.translate.xml:8376 book.translate.xml:9969 #: book.translate.xml:10042 book.translate.xml:11612 msgid "vnodelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8236 book.translate.xml:11613 msgid "Existing policy label for vp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8241 book.translate.xml:8702 book.translate.xml:8768 #: book.translate.xml:8832 book.translate.xml:9779 book.translate.xml:10184 #: book.translate.xml:10893 book.translate.xml:11435 book.translate.xml:11500 #: book.translate.xml:11550 book.translate.xml:11618 msgid "newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8242 msgid "" "New, possibly partial label to replace vnodelabel" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8249 msgid "" "Update the label on the passed vnode given the passed update vnode label and " "the passed subject credential." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8255 msgid "mpo_setlabel_vnode_extattr" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8258 msgid "" "int mpo_setlabel_vnode_extattr " "struct ucred *cred " "struct vnode *vp " "struct label *vlabel " "struct label *intlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8297 msgid "Vnode for which the label is being written" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8308 msgid "intlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8309 msgid "Label to write out" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8315 msgid "" "Write out the policy from intlabel to an extended " "attribute. This is called from vop_stdcreatevnode_ea." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8322 msgid "mpo_update_devfsdirent" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8325 msgid "" "void mpo_update_devfsdirent " "struct devfs_dirent *devfs_dirent struct label *direntlabel struct vnode *vp " "struct label *vnodelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8359 msgid "Object; devfs directory entry" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8363 msgid "direntlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8364 msgid "Policy label for devfs_dirent to be updated." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8371 msgid "Parent vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8372 book.translate.xml:9965 book.translate.xml:11608 #: book.translate.xml:12162 msgid "Locked" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8377 book.translate.xml:9970 book.translate.xml:10043 #: book.translate.xml:11802 book.translate.xml:12089 book.translate.xml:12167 #: book.translate.xml:12234 book.translate.xml:12299 book.translate.xml:12372 #: book.translate.xml:13079 book.translate.xml:13204 book.translate.xml:13270 #: book.translate.xml:13336 book.translate.xml:13414 book.translate.xml:13500 #: book.translate.xml:13568 book.translate.xml:13637 book.translate.xml:13709 #: book.translate.xml:13897 msgid "Policy label for vp" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8384 msgid "" "Update the devfs_dirent label from the passed devfs " "vnode label. This call will be made when a devfs vnode has been successfully " "relabeled to commit the label change such that it lasts even if the vnode is " "recycled. It will also be made when a symlink is created in devfs, following " "a call to mac_vnode_create_from_vnode to initialize the " "vnode label." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:8396 msgid "IPC Object Labeling Event Operations" msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8399 msgid "mpo_create_mbuf_from_socket" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8402 msgid "" "void mpo_create_mbuf_from_socket " "struct socket *so " "struct label *socketlabel " "struct mbuf *m struct " "label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8435 book.translate.xml:11062 book.translate.xml:11124 #: book.translate.xml:11368 book.translate.xml:11489 book.translate.xml:12945 msgid "socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8436 book.translate.xml:11194 book.translate.xml:11252 msgid "Socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8437 msgid "Socket locking WIP" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8441 book.translate.xml:8570 book.translate.xml:11067 #: book.translate.xml:11129 book.translate.xml:11198 book.translate.xml:11256 #: book.translate.xml:11373 book.translate.xml:11494 book.translate.xml:12950 #: book.translate.xml:14114 msgid "socketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8442 book.translate.xml:11068 book.translate.xml:11130 #: book.translate.xml:11374 book.translate.xml:12951 msgid "Policy label for socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8447 msgid "m" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8448 msgid "Object; mbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8452 book.translate.xml:8822 book.translate.xml:9349 #: book.translate.xml:9417 book.translate.xml:9484 book.translate.xml:9835 #: book.translate.xml:13975 book.translate.xml:14051 msgid "mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8453 msgid "Policy label to fill in for m" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8460 msgid "" "Set the label on a newly created mbuf header from the passed socket label. " "This call is made when a new datagram or message is generated by the socket " "and stored in the passed mbuf." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8467 msgid "mpo_create_pipe" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8470 msgid "" "void mpo_create_pipe " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8506 book.translate.xml:8691 book.translate.xml:10699 #: book.translate.xml:10766 book.translate.xml:10823 book.translate.xml:10882 #: book.translate.xml:10945 book.translate.xml:11003 msgid "pipe" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8507 book.translate.xml:8692 book.translate.xml:10700 #: book.translate.xml:10767 book.translate.xml:10824 book.translate.xml:10883 #: book.translate.xml:10946 book.translate.xml:11004 msgid "Pipe" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8511 book.translate.xml:10704 book.translate.xml:10771 #: book.translate.xml:10828 book.translate.xml:10887 book.translate.xml:10950 #: book.translate.xml:11008 msgid "pipelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8512 book.translate.xml:10705 book.translate.xml:10772 #: book.translate.xml:10829 book.translate.xml:10951 book.translate.xml:11009 msgid "Policy label associated with pipe" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8519 msgid "" "Set the label on a newly created pipe from the passed subject credential. " "This call is made when a new pipe is created." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8525 msgid "mpo_create_socket" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8528 msgid "" "void mpo_create_socket " "struct ucred *cred " "struct socket *so " "struct label *socketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8561 book.translate.xml:8753 book.translate.xml:8954 #: book.translate.xml:9955 book.translate.xml:10033 book.translate.xml:11602 #: book.translate.xml:11732 book.translate.xml:12156 book.translate.xml:14105 msgid "Immutable" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8565 book.translate.xml:8757 book.translate.xml:11193 #: book.translate.xml:11251 book.translate.xml:14109 msgid "so" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8566 msgid "Object; socket to label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8571 msgid "Label to fill in for so" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8578 msgid "" "Set the label on a newly created socket from the passed subject credential. " "This call is made when a socket is created." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8584 msgid "mpo_create_socket_from_socket" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8587 msgid "" "void mpo_create_socket_from_socket " "struct socket *oldsocket " "struct label *oldsocketlabel " "struct socket *newsocket " "struct label *newsocketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8620 book.translate.xml:8882 msgid "oldsocket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8621 msgid "Listening socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8625 book.translate.xml:8887 msgid "oldsocketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8626 msgid "Policy label associated with oldsocket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8631 book.translate.xml:8893 msgid "newsocket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8632 msgid "New socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8636 msgid "newsocketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8637 msgid "Policy label associated with newsocketlabel" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8644 msgid "" "Label a socket, newsocket, newly " "accept2ed, based on the listen2 socket, " "oldsocket." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8650 msgid "mpo_relabel_pipe" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8653 msgid "" "void mpo_relabel_pipe " "struct ucred *cred " "struct pipe *pipe " "struct label *oldlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8696 book.translate.xml:8762 book.translate.xml:8827 msgid "oldlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8697 book.translate.xml:10888 msgid "Current policy label associated with pipe" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8703 msgid "Policy label update to apply to pipe" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8710 msgid "" "Apply a new label, newlabel, to pipe." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8715 msgid "mpo_relabel_socket" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8718 msgid "" "void mpo_relabel_socket " "struct ucred *cred " "struct socket *so " "struct label *oldlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8758 book.translate.xml:11369 book.translate.xml:11490 #: book.translate.xml:12946 book.translate.xml:14110 msgid "Object; socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8763 msgid "Current label for so" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8769 msgid "Label update for so" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8776 msgid "Update the label on a socket from the passed socket label update." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8781 msgid "mpo_set_socket_peer_from_mbuf" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8784 msgid "" "void mpo_set_socket_peer_from_mbuf " "struct mbuf *mbuf " "struct label *mbuflabel " "struct label *oldlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8817 book.translate.xml:9344 book.translate.xml:9412 #: book.translate.xml:9479 book.translate.xml:9830 book.translate.xml:13970 #: book.translate.xml:14046 msgid "mbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8818 msgid "First datagram received over socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8823 msgid "Label for mbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8828 msgid "Current label for the socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8833 msgid "Policy label to be filled out for the socket" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8840 msgid "" "Set the peer label on a stream socket from the passed mbuf label. This call " "will be made when the first datagram is received by the stream socket, with " "the exception of Unix domain sockets." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8847 msgid "mpo_set_socket_peer_from_socket" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8850 msgid "" "void mpo_set_socket_peer_from_socket " "struct socket *oldsocket " "struct label *oldsocketlabel " "struct socket *newsocket " "struct label *newsocketpeerlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8883 msgid "Local socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8888 msgid "Policy label for oldsocket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8894 msgid "Peer socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8898 msgid "newsocketpeerlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8899 msgid "Policy label to fill in for newsocket" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8907 msgid "" "Set the peer label on a stream UNIX domain socket from the passed remote " "socket endpoint. This call will be made when the socket pair is connected, " "and will be made for both endpoints." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:8915 msgid "Network Object Labeling Event Operations" msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8918 msgid "mpo_create_bpfdesc" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8921 msgid "" "void mpo_create_bpfdesc " "struct ucred *cred " "struct bpf_d *bpf_d " "struct label *bpflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8958 book.translate.xml:9401 book.translate.xml:10294 msgid "bpf_d" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8959 msgid "Object; bpf descriptor" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8963 msgid "bpf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:8964 msgid "Policy label to be filled in for bpf_d" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:8971 msgid "" "Set the label on a newly created BPF descriptor from the passed subject " "credential. This call will be made when a BPF device node is opened by a " "process with the passed subject credential." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:8978 msgid "mpo_create_ifnet" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:8981 msgid "" "void mpo_create_ifnet " "struct ifnet *ifnet " "struct label *ifnetlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9010 book.translate.xml:9333 book.translate.xml:9468 #: book.translate.xml:9548 book.translate.xml:9768 book.translate.xml:10305 #: book.translate.xml:11424 book.translate.xml:13959 book.translate.xml:14035 msgid "ifnet" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9011 book.translate.xml:9334 book.translate.xml:9469 #: book.translate.xml:9549 book.translate.xml:13960 book.translate.xml:14036 msgid "Network interface" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9015 book.translate.xml:9338 book.translate.xml:9473 #: book.translate.xml:9553 book.translate.xml:9773 book.translate.xml:10310 #: book.translate.xml:11429 book.translate.xml:13964 book.translate.xml:14040 msgid "ifnetlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9016 msgid "Policy label to fill in for ifnet" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9023 msgid "" "Set the label on a newly created interface. This call may be made when a new " "physical interface becomes available to the system, or when a pseudo-" "interface is instantiated during the boot or as a result of a user action." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9031 msgid "mpo_create_ipq" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9034 msgid "" "void mpo_create_ipq struct " "mbuf *fragment struct label " "*fragmentlabel struct ipq " "*ipq struct label " "*ipqlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9067 book.translate.xml:9210 book.translate.xml:9686 msgid "fragment" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9068 msgid "First received IP fragment" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9072 book.translate.xml:9215 book.translate.xml:9691 msgid "fragmentlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9073 book.translate.xml:9692 msgid "Policy label for fragment" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9078 book.translate.xml:9133 book.translate.xml:9697 #: book.translate.xml:9841 msgid "ipq" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9079 msgid "IP reassembly queue to be labeled" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9083 book.translate.xml:9138 book.translate.xml:9702 #: book.translate.xml:9846 msgid "ipqlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9084 msgid "Policy label to be filled in for ipq" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9091 msgid "" "Set the label on a newly created IP fragment reassembly queue from the mbuf " "header of the first received fragment." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9097 msgid "mpo_create_datagram_from_ipq" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9100 msgid "" "void mpo_create_create_datagram_from_ipq struct ipq *ipq " "struct label *ipqlabel " "struct mbuf *datagram " "struct label *datagramlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9134 msgid "IP reassembly queue" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9139 book.translate.xml:9703 msgid "Policy label for ipq" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9144 book.translate.xml:9199 msgid "datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9145 msgid "Datagram to be labeled" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9149 book.translate.xml:9204 msgid "datagramlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9150 msgid "Policy label to be filled in for datagramlabel" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9157 msgid "" "Set the label on a newly reassembled IP datagram from the IP fragment " "reassembly queue from which it was generated." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9163 msgid "mpo_create_fragment" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9166 msgid "" "void mpo_create_fragment " "struct mbuf *datagram " "struct label *datagramlabel " "struct mbuf *fragment " "struct label *fragmentlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9200 msgid "Datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9205 msgid "Policy label for datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9211 msgid "Fragment to be labeled" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9216 msgid "Policy label to be filled in for datagram" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9223 msgid "" "Set the label on the mbuf header of a newly created IP fragment from the " "label on the mbuf header of the datagram it was generate from." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9229 msgid "mpo_create_mbuf_from_mbuf" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9232 msgid "" "void mpo_create_mbuf_from_mbuf " "struct mbuf *oldmbuf " "struct label *oldmbuflabel " "struct mbuf *newmbuf " "struct label *newmbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9265 book.translate.xml:9537 book.translate.xml:9617 msgid "oldmbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9266 msgid "Existing (source) mbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9270 book.translate.xml:9542 book.translate.xml:9622 msgid "oldmbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9271 book.translate.xml:9543 book.translate.xml:9623 msgid "Policy label for oldmbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9276 book.translate.xml:9559 book.translate.xml:9628 msgid "newmbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9277 book.translate.xml:9413 msgid "New mbuf to be labeled" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9281 book.translate.xml:9565 book.translate.xml:9633 msgid "newmbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9282 book.translate.xml:9566 msgid "Policy label to be filled in for newmbuf" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9289 msgid "" "Set the label on the mbuf header of a newly created datagram from the mbuf " "header of an existing datagram. This call may be made in a number of " "situations, including when an mbuf is re-allocated for alignment purposes." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9297 msgid "mpo_create_mbuf_linklayer" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9300 msgid "" "void mpo_create_mbuf_linklayer " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct mbuf *mbuf " "struct label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9339 book.translate.xml:9554 book.translate.xml:9774 #: book.translate.xml:10311 book.translate.xml:13965 book.translate.xml:14041 msgid "Policy label for ifnet" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9345 book.translate.xml:9480 msgid "mbuf header for new datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9350 book.translate.xml:9485 msgid "Policy label to be filled in for mbuf" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9357 msgid "" "Set the label on the mbuf header of a newly created datagram generated for " "the purposes of a link layer response for the passed interface. This call " "may be made in a number of situations, including for ARP or ND6 responses in " "the IPv4 and IPv6 stacks." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9365 msgid "mpo_create_mbuf_from_bpfdesc" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9368 msgid "" "void mpo_create_mbuf_from_bpfdesc " "struct bpf_d *bpf_d " "struct label *bpflabel " "struct mbuf *mbuf " "struct label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9402 msgid "BPF descriptor" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9406 book.translate.xml:10299 msgid "bpflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9407 msgid "Policy label for bpflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9418 msgid "Policy label to fill in for mbuf" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9425 msgid "" "Set the label on the mbuf header of a newly created datagram generated using " "the passed BPF descriptor. This call is made when a write is performed to " "the BPF device associated with the passed BPF descriptor." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9432 msgid "mpo_create_mbuf_from_ifnet" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9435 msgid "" "void mpo_create_mbuf_from_ifnet " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct mbuf *mbuf " "struct label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9474 msgid "Policy label for ifnetlabel" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9492 msgid "" "Set the label on the mbuf header of a newly created datagram generated from " "the passed network interface." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9498 msgid "mpo_create_mbuf_multicast_encap" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9501 msgid "" "void mpo_create_mbuf_multicast_encap " "struct mbuf *oldmbuf " "struct label *oldmbuflabel " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct mbuf *newmbuf " "struct label *newmbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9538 msgid "mbuf header for existing datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9560 msgid "mbuf header to be labeled for new datagram" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9573 msgid "" "Set the label on the mbuf header of a newly created datagram generated from " "the existing passed datagram when it is processed by the passed multicast " "encapsulation interface. This call is made when an mbuf is to be delivered " "using the virtual interface." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9581 msgid "mpo_create_mbuf_netlayer" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9584 msgid "" "void mpo_create_mbuf_netlayer " "struct mbuf *oldmbuf " "struct label *oldmbuflabel " "struct mbuf *newmbuf " "struct label *newmbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9618 msgid "Received datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9629 msgid "Newly created datagram" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9634 msgid "Policy label for newmbuf" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9641 msgid "" "Set the label on the mbuf header of a newly created datagram generated by " "the IP stack in response to an existing received datagram " "(oldmbuf). This call may be made in a number of " "situations, including when responding to ICMP request datagrams." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9650 msgid "mpo_fragment_match" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9653 msgid "" "int mpo_fragment_match " "struct mbuf *fragment " "struct label *fragmentlabel " "struct ipq *ipq struct " "label *ipqlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9687 msgid "IP datagram fragment" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9698 book.translate.xml:9842 msgid "IP fragment reassembly queue" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9710 msgid "" "Determine whether an mbuf header containing an IP datagram " "(fragment) fragment matches the label of the passed " "IP fragment reassembly queue (ipq). Return " "(1) for a successful match, or (0) for no match. This call is made when the IP stack attempts to " "find an existing fragment reassembly queue for a newly received fragment; if " "this fails, a new fragment reassembly queue may be instantiated for the " "fragment. Policies may use this entry point to prevent the reassembly of " "otherwise matching IP fragments if policy does not permit them to be " "reassembled based on the label or other information." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9727 msgid "mpo_relabel_ifnet" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9730 msgid "" "void mpo_relabel_ifnet " "struct ucred *cred " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9769 msgid "Object; Network interface" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9780 msgid "Label update to apply to ifnet" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9787 msgid "" "Update the label of network interface, ifnet, based " "on the passed update label, newlabel, and the passed " "subject credential, cred." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9794 msgid "mpo_update_ipq" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9797 msgid "" "void mpo_update_ipq struct " "mbuf *fragment struct label " "*fragmentlabel struct ipq " "*ipq struct label " "*ipqlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9831 msgid "IP fragment" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9836 book.translate.xml:13976 book.translate.xml:14052 msgid "Policy label for mbuf" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9847 msgid "Policy label to be updated for ipq" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9854 msgid "" "Update the label on an IP fragment reassembly queue (ipq) based on the acceptance of the passed IP fragment mbuf header " "(mbuf)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:9862 msgid "Process Labeling Event Operations" msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9865 msgid "mpo_create_cred" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9868 msgid "" "void mpo_create_cred " "struct ucred *parent_cred " "struct ucred *child_cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9897 msgid "parent_cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9898 msgid "Parent subject credential" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9902 msgid "child_cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9903 msgid "Child subject credential" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9909 msgid "" "Set the label of a newly created subject credential from the passed subject " "credential. This call will be made when crcopy9 is invoked on a newly " "created struct ucred. This call should not be confused with a " "process forking or creation event." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9917 msgid "mpo_execve_transition" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9920 msgid "" "void mpo_execve_transition " "struct ucred *old " "struct ucred *new " "struct vnode *vp " "struct label *vnodelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9953 book.translate.xml:10030 book.translate.xml:14434 msgid "old" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9954 msgid "Existing subject credential" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9959 book.translate.xml:14448 msgid "new" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9960 msgid "New subject credential to be labeled" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:9965 book.translate.xml:10038 msgid "File to execute" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:9977 msgid "" "Update the label of a newly created subject credential (new) from the passed existing subject credential (old) based on a label transition caused by executing the passed vnode " "(vp). This call occurs when a process executes the " "passed vnode and one of the policies returns a success from the " "mpo_execve_will_transition entry point. Policies may " "choose to implement this call simply by invoking mpo_create_cred and passing the two subject credentials so as not to implement a " "transitioning event. Policies should not leave this entry point " "unimplemented if they implement mpo_create_cred, even " "if they do not implement mpo_execve_will_transition." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:9996 msgid "mpo_execve_will_transition" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:9999 msgid "" "int mpo_execve_will_transition " "struct ucred *old " "struct vnode *vp " "struct label *vnodelabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10031 msgid "" "Subject credential prior to execve2" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:10050 msgid "" "Determine whether the policy will want to perform a transition event as a " "result of the execution of the passed vnode by the passed subject credential." " Return 1 if a transition is required, " "0 if not. Even if a policy returns " "0, it should behave correctly in the presence of " "an unexpected invocation of mpo_execve_transition, as " "that call may happen as a result of another policy requesting a transition." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:10063 msgid "mpo_create_proc0" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10066 msgid "" "void mpo_create_proc0 " "struct ucred *cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10094 book.translate.xml:10136 msgid "Subject credential to be filled in" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:10100 msgid "" "Create the subject credential of process 0, the parent of all kernel " "processes." msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:10105 msgid "mpo_create_proc1" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10108 msgid "" "void mpo_create_proc1 " "struct ucred *cred" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:10142 msgid "" "Create the subject credential of process 1, the parent of all user processes." "" msgstr "" #. (itstool) path: sect4/title #: book.translate.xml:10147 msgid "mpo_relabel_cred" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10150 msgid "" "void mpo_relabel_cred " "struct ucred *cred " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10185 msgid "Label update to apply to cred" msgstr "" #. (itstool) path: sect4/para #: book.translate.xml:10192 msgid "Update the label on a subject credential from the passed update label." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:10200 msgid "Access Control Checks" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:10202 msgid "" "Access control entry points permit policy modules to influence access " "control decisions made by the kernel. Generally, although not always, " "arguments to an access control entry point will include one or more " "authorizing credentials, information (possibly including a label) for any " "other objects involved in the operation. An access control entry point may " "return 0 to permit the operation, or an errno2 error value. The " "results of invoking the entry point across various registered policy modules " "will be composed as follows: if all modules permit the operation to succeed, " "success will be returned. If one or modules returns a failure, a failure " "will be returned. If more than one module returns a failure, the errno value " "to return to the user will be selected using the following precedence, " "implemented by the error_select() function in " "kern_mac.c:" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10223 msgid "Most precedence" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10224 msgid "EDEADLK" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10229 msgid "EINVAL" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10234 msgid "ESRCH" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10239 msgid "EACCES" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10243 msgid "Least precedence" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10244 msgid "EPERM" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:10250 msgid "" "If none of the error values returned by all modules are listed in the " "precedence chart then an arbitrarily selected value from the set will be " "returned. In general, the rules provide precedence to errors in the " "following order: kernel failures, invalid arguments, object not present, " "access not permitted, other." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10258 msgid "mpo_check_bpfdesc_receive" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10261 msgid "" "int mpo_check_bpfdesc_receive " "struct bpf_d *bpf_d " "struct label *bpflabel " "struct ifnet *ifnet " "struct label *ifnetlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10295 msgid "Subject; BPF descriptor" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10300 msgid "Policy label for bpf_d" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10306 book.translate.xml:11425 msgid "Object; network interface" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10318 msgid "" "Determine whether the MAC framework should permit datagrams from the passed " "interface to be delivered to the buffers of the passed BPF descriptor. " "Return (0) for success, or an errno value for failure Suggested failure: EACCES " "for label mismatches, EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10328 msgid "mpo_check_kenv_dump" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10331 msgid "" "int mpo_check_kenv_dump " "struct ucred *cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10365 msgid "" "Determine whether the subject should be allowed to retrieve the kernel " "environment (see kenv2)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10370 msgid "mpo_check_kenv_get" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10373 msgid "" "int mpo_check_kenv_get " "struct ucred *cred " "char *name" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10406 book.translate.xml:10455 book.translate.xml:10503 #: book.translate.xml:12382 book.translate.xml:13424 book.translate.xml:14425 msgid "name" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10407 book.translate.xml:10456 book.translate.xml:10504 msgid "Kernel environment variable name" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10413 msgid "" "Determine whether the subject should be allowed to retrieve the value of the " "specified kernel environment variable." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10419 msgid "mpo_check_kenv_set" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10422 msgid "" "int mpo_check_kenv_set " "struct ucred *cred " "char *name" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10462 msgid "" "Determine whether the subject should be allowed to set the specified kernel " "environment variable." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10467 msgid "mpo_check_kenv_unset" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10470 msgid "" "int mpo_check_kenv_unset " "struct ucred *cred " "char *name" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10510 msgid "" "Determine whether the subject should be allowed to unset the specified " "kernel environment variable." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10515 msgid "mpo_check_kld_load" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10518 msgid "" "int mpo_check_kld_load " "struct ucred *cred " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10555 msgid "Kernel module vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10560 book.translate.xml:14179 book.translate.xml:14370 msgid "Label associated with vp" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10567 msgid "" "Determine whether the subject should be allowed to load the specified module " "file." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10572 msgid "mpo_check_kld_stat" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10575 msgid "" "int mpo_check_kld_stat " "struct ucred *cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10609 msgid "" "Determine whether the subject should be allowed to retrieve a list of loaded " "kernel module files and associated statistics." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10615 msgid "mpo_check_kld_unload" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10618 msgid "" "int mpo_check_kld_unload " "struct ucred *cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10652 msgid "" "Determine whether the subject should be allowed to unload a kernel module." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10657 msgid "mpo_check_pipe_ioctl" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10660 msgid "" "int mpo_check_pipe_ioctl " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel " "unsigned long cmd void " "*data" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10710 msgid "cmd" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10711 msgid "" "ioctl2 command" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10715 msgid "data" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10716 msgid "" "ioctl2 data" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10722 msgid "" "Determine whether the subject should be allowed to make the specified " "ioctl2 call." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10727 msgid "mpo_check_pipe_poll" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10730 msgid "" "int mpo_check_pipe_poll " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10779 msgid "" "Determine whether the subject should be allowed to poll pipe." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10784 msgid "mpo_check_pipe_read" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10787 msgid "" "int mpo_check_pipe_read " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10836 msgid "" "Determine whether the subject should be allowed read access to " "pipe." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10841 msgid "mpo_check_pipe_relabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10844 msgid "" "int mpo_check_pipe_relabel " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:10894 msgid "Label update to pipelabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10901 msgid "" "Determine whether the subject should be allowed to relabel pipe." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10906 msgid "mpo_check_pipe_stat" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10909 msgid "" "int mpo_check_pipe_stat " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:10958 msgid "" "Determine whether the subject should be allowed to retrieve statistics " "related to pipe." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:10964 msgid "mpo_check_pipe_write" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:10967 msgid "" "int mpo_check_pipe_write " "struct ucred *cred " "struct pipe *pipe " "struct label *pipelabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11016 msgid "" "Determine whether the subject should be allowed to write to pipe." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11021 msgid "mpo_check_socket_bind" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11024 msgid "" "int mpo_check_socket_bind " "struct ucred *cred " "struct socket *socket " "struct label *socketlabel " "struct sockaddr *sockaddr" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11063 msgid "Socket to be bound" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11073 book.translate.xml:11135 msgid "sockaddr" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11074 book.translate.xml:11136 msgid "Address of socket" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11083 msgid "mpo_check_socket_connect" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11086 msgid "" "int mpo_check_socket_connect " "struct ucred *cred " "struct socket *socket " "struct label *socketlabel " "struct sockaddr *sockaddr" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11125 msgid "Socket to be connected" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11143 msgid "" "Determine whether the subject credential (cred) can " "connect the passed socket (socket) to the passed " "socket address (sockaddr). Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatches, " "EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11154 msgid "mpo_check_socket_receive" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11157 msgid "" "int mpo_check_socket_receive " "struct ucred *cred " "struct socket *so " "struct label *socketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11199 book.translate.xml:11257 msgid "Policy label associated with so" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11206 msgid "" "Determine whether the subject should be allowed to receive information from " "the socket so." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11212 msgid "mpo_check_socket_send" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11215 msgid "" "int mpo_check_socket_send " "struct ucred *cred " "struct socket *so " "struct label *socketlabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11264 msgid "" "Determine whether the subject should be allowed to send information across " "the socket so." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11270 msgid "mpo_check_cred_visible" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11273 msgid "" "int mpo_check_cred_visible " "struct ucred *u1 " "struct ucred *u2" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11302 msgid "u1" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11307 msgid "u2" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11308 msgid "Object credential" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11314 msgid "" "Determine whether the subject credential u1 can " "see other subjects with the passed subject credential " "u2. Return 0 for success, " "or an errno value for failure. Suggested failure: " "EACCES for label mismatches, EPERM for lack of privilege, or ESRCH to hide " "visibility. This call may be made in a number of situations, including inter-" "process status sysctl's used by ps, and in procfs lookups." "" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11329 book.translate.xml:14069 msgid "mpo_check_socket_visible" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11332 msgid "" "int mpo_check_socket_visible " "struct ucred *cred " "struct socket *socket " "struct label *socketlabel" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11383 msgid "mpo_check_ifnet_relabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11386 msgid "" "int mpo_check_ifnet_relabel " "struct ucred *cred " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11430 msgid "Existing policy label for ifnet" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11436 msgid "" "Policy label update to later be applied to ifnet" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11443 msgid "" "Determine whether the subject credential can relabel the passed network " "interface to the passed label update." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11448 msgid "mpo_check_socket_relabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11451 msgid "" "int mpo_check_socket_relabel " "struct ucred *cred " "struct socket *socket " "struct label *socketlabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11495 msgid "Existing policy label for socket" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11501 msgid "Label update to later be applied to socketlabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11508 msgid "" "Determine whether the subject credential can relabel the passed socket to " "the passed label update." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11513 msgid "mpo_check_cred_relabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11516 msgid "" "int mpo_check_cred_relabel " "struct ucred *cred " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11551 msgid "Label update to later be applied to cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11558 msgid "" "Determine whether the subject credential can relabel itself to the passed " "label update." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11564 msgid "mpo_check_vnode_relabel" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11567 msgid "" "int mpo_check_vnode_relabel " "struct ucred *cred " "struct vnode *vp " "struct label *vnodelabel " "struct label *newlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11607 book.translate.xml:11797 book.translate.xml:11991 #: book.translate.xml:12161 book.translate.xml:12294 book.translate.xml:12367 #: book.translate.xml:13006 book.translate.xml:13074 book.translate.xml:13199 #: book.translate.xml:13265 book.translate.xml:13331 book.translate.xml:13409 #: book.translate.xml:13495 book.translate.xml:13563 book.translate.xml:13632 #: book.translate.xml:13892 msgid "Object; vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11619 msgid "Policy label update to later be applied to vp" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11626 msgid "" "Determine whether the subject credential can relabel the passed vnode to the " "passed label update." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11631 msgid "mpo_check_mount_stat" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11634 msgid "" "int mpo_check_mount_stat " "struct ucred *cred " "struct mount *mp " "struct label *mountlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11671 msgid "Object; file system mount" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11675 msgid "mountlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11676 msgid "Policy label for mp" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11684 msgid "" "Determine whether the subject credential can see the results of a statfs " "performed on the file system. Return 0 for " "success, or an errno value for failure. Suggested failure:" " EACCES for label mismatches or EPERM for lack of privilege. This call may be made in a number of " "situations, including during invocations of " "statfs2 and related calls, as well as to determine what file systems " "to exclude from listings of file systems, such as when " "getfsstat2 is invoked." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11698 msgid "mpo_check_proc_debug" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11701 msgid "" "int mpo_check_proc_debug " "struct ucred *cred " "struct proc *proc" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11736 book.translate.xml:13773 book.translate.xml:13830 msgid "proc" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11737 book.translate.xml:13774 book.translate.xml:13831 msgid "Object; process" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11743 msgid "" "Determine whether the subject credential can debug the passed process. " "Return 0 for success, or an errno value for failure. Suggested failure: EACCES " "for label mismatch, EPERM for lack of privilege, or " "ESRCH to hide visibility of the target. This call may " "be made in a number of situations, including use of the " "ptrace2 and ktrace2 APIs, as well as for " "some types of procfs operations." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11756 msgid "mpo_check_vnode_access" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11759 msgid "" "int mpo_check_vnode_access " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int flags" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11807 book.translate.xml:13505 msgid "flags" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11808 msgid "" "access2 flags" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11814 msgid "" "Determine how invocations of access2 and related calls by " "the subject credential should return when performed on the passed vnode " "using the passed access flags. This should generally be implemented using " "the same semantics used in mpo_check_vnode_open. Return " "0 for success, or an errno " "value for failure. Suggested failure: EACCES for " "label mismatches or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11827 msgid "mpo_check_vnode_chdir" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11830 msgid "" "int mpo_check_vnode_chdir " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11867 msgid "" "Object; vnode to chdir2 into" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11872 book.translate.xml:11996 book.translate.xml:12078 #: book.translate.xml:13011 book.translate.xml:13142 msgid "Policy label for dvp" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11879 msgid "" "Determine whether the subject credential can change the process working " "directory to the passed vnode. Return 0 for " "success, or an errno value for failure. Suggested failure:" " EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11889 msgid "mpo_check_vnode_chroot" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11892 msgid "" "int mpo_check_vnode_chroot " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11929 book.translate.xml:12453 book.translate.xml:12781 #: book.translate.xml:12863 msgid "Directory vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:11934 book.translate.xml:12458 book.translate.xml:12786 #: book.translate.xml:12868 msgid "Policy label associated with dvp" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:11941 msgid "" "Determine whether the subject should be allowed to " "chroot2 into the specified directory (dvp)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:11947 msgid "mpo_check_vnode_create" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:11950 msgid "" "int mpo_check_vnode_create " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel " "struct componentname *cnp " "struct vattr *vap" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12002 msgid "Component name for dvp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12007 msgid "vap" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12008 msgid "vnode attributes for vap" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12015 msgid "" "Determine whether the subject credential can create a vnode with the passed " "parent directory, passed name information, and passed attribute information. " "Return 0 for success, or an errno value for failure. Suggested failure: EACCES " "for label mismatch, or EPERM for lack of privilege. " "This call may be made in a number of situations, including as a result of " "calls to open2 with O_CREAT, " "mkfifo2, and others." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12028 msgid "mpo_check_vnode_delete" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12031 msgid "" "int mpo_check_vnode_delete " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel " "struct vnode *vp void " "*label struct componentname " "*cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12084 msgid "Object; vnode to delete" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12102 msgid "" "Determine whether the subject credential can delete a vnode from the passed " "parent directory and passed name information. Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatch, or " "EPERM for lack of privilege. This call may be made in " "a number of situations, including as a result of calls to " "unlink2 and rmdir2. Policies implementing " "this entry point should also implement mpo_check_rename_to to authorize deletion of objects as a result of being the target " "of a rename." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12118 msgid "mpo_check_vnode_deleteacl" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12121 msgid "" "int mpo_check_vnode_deleteacl " "struct ucred *cred " "struct vnode *vp " "struct label *label " "acl_type_t type" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12172 book.translate.xml:12304 book.translate.xml:13341 msgid "type" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12173 book.translate.xml:12305 book.translate.xml:13342 msgid "ACL type" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12179 msgid "" "Determine whether the subject credential can delete the ACL of passed type " "from the passed vnode. Return 0 for success, or " "an errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12189 msgid "mpo_check_vnode_exec" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12192 msgid "" "int mpo_check_vnode_exec " "struct ucred *cred " "struct vnode *vp " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12229 msgid "Object; vnode to execute" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12241 msgid "" "Determine whether the subject credential can execute the passed vnode. " "Determination of execute privilege is made separately from decisions about " "any transitioning event. Return 0 for success, or " "an errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12252 msgid "mpo_check_vnode_getacl" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12255 msgid "" "int mpo_check_vnode_getacl " "struct ucred *cred " "struct vnode *vp " "struct label *label " "acl_type_t type" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12311 msgid "" "Determine whether the subject credential can retrieve the ACL of passed type " "from the passed vnode. Return 0 for success, or " "an errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12321 msgid "mpo_check_vnode_getextattr" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12324 msgid "" "int mpo_check_vnode_getextattr " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int attrnamespace " "const char *name " "struct uio *uio" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12377 book.translate.xml:13419 msgid "attrnamespace" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12378 book.translate.xml:13420 msgid "Extended attribute namespace" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12383 book.translate.xml:13425 msgid "Extended attribute name" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12387 book.translate.xml:13429 msgid "uio" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12388 book.translate.xml:13430 msgid "" "I/O structure pointer; see uio9" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12394 msgid "" "Determine whether the subject credential can retrieve the extended attribute " "with the passed namespace and name from the passed vnode. Policies " "implementing labeling using extended attributes may be interested in special " "handling of operations on those extended attributes. Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatch, or " "EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12407 msgid "mpo_check_vnode_link" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12410 msgid "" "int mpo_check_vnode_link " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel " "struct vnode *vp " "struct label *label " "struct componentname *cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12464 msgid "Link destination vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12475 msgid "Component name for the link being created" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12482 msgid "" "Determine whether the subject should be allowed to create a link to the " "vnode vp with the name specified by cnp." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12488 msgid "mpo_check_vnode_mmap" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12491 msgid "" "int mpo_check_vnode_mmap " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int prot" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12529 msgid "Vnode to map" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12539 book.translate.xml:12600 book.translate.xml:12657 msgid "prot" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12540 msgid "" "Mmap protections (see mmap2)" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12546 msgid "" "Determine whether the subject should be allowed to map the vnode " "vp with the protections specified in prot." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12552 msgid "mpo_check_vnode_mmap_downgrade" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12555 msgid "" "void mpo_check_vnode_mmap_downgrade " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int *prot" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12588 msgid "See ." msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12601 msgid "Mmap protections to be downgraded" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12607 msgid "Downgrade the mmap protections based on the subject and object labels." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12612 msgid "mpo_check_vnode_mprotect" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12615 msgid "" "int mpo_check_vnode_mprotect " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int prot" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12653 msgid "Mapped vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12658 msgid "Memory protections" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12664 msgid "" "Determine whether the subject should be allowed to set the specified memory " "protections on memory mapped from the vnode vp." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12670 msgid "mpo_check_vnode_poll" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12673 msgid "" "int mpo_check_vnode_poll " "struct ucred *active_cred " "struct ucred *file_cred " "struct vnode *vp " "struct label *label" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12706 msgid "active_cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12711 msgid "file_cred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12712 msgid "Credential associated with the struct file" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12718 msgid "Polled vnode" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12730 msgid "" "Determine whether the subject should be allowed to poll the vnode " "vp." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12735 msgid "mpo_check_vnode_rename_from" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12738 msgid "" "int mpo_vnode_rename_from " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel " "struct vnode *vp " "struct label *label " "struct componentname *cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12792 msgid "Vnode to be renamed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12810 msgid "" "Determine whether the subject should be allowed to rename the vnode " "vp to something else." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12816 msgid "mpo_check_vnode_rename_to" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12819 msgid "" "int mpo_check_vnode_rename_to " "struct ucred *cred " "struct vnode *dvp " "struct label *dlabel " "struct vnode *vp " "struct label *label " "int samedir struct " "componentname *cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12874 msgid "Overwritten vnode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12884 msgid "samedir" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12885 msgid "" "Boolean; 1 if the source and destination directories are " "the same" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:12891 msgid "Destination component name" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12897 msgid "" "Determine whether the subject should be allowed to rename to the vnode " "vp, into the directory dvp, or " "to the name represented by cnp. If there is no " "existing file to overwrite, vp and label will be NULL." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12906 msgid "mpo_check_socket_listen" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12909 msgid "" "int mpo_check_socket_listen " "struct ucred *cred " "struct socket *socket " "struct label *socketlabel" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:12958 msgid "" "Determine whether the subject credential can listen on the passed socket. " "Return 0 for success, or an errno value for failure. Suggested failure: EACCES " "for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:12967 msgid "mpo_check_vnode_lookup" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:12970 msgid "" "int mpo_check_vnode_lookup " "struct ucred *cred struct vnode " "*dvp struct label *dlabel struct componentname *cnp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13017 msgid "Component name being looked up" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13023 msgid "" "Determine whether the subject credential can perform a lookup in the passed " "directory vnode for the passed name. Return 0 for " "success, or an errno value for failure. Suggested failure:" " EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13033 msgid "mpo_check_vnode_open" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13036 msgid "" "int mpo_check_vnode_open " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int acc_mode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13084 msgid "acc_mode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13085 msgid "" "open2 access mode" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13091 msgid "" "Determine whether the subject credential can perform an open operation on " "the passed vnode with the passed access mode. Return 0 for success, or an errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13100 msgid "mpo_check_vnode_readdir" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13103 msgid "" "int mpo_check_vnode_readdir " "struct ucred *cred struct vnode " "*dvp struct label *dlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13137 msgid "Object; directory vnode" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13149 msgid "" "Determine whether the subject credential can perform a readdir operation on the passed directory vnode. Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatch, or " "EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13159 msgid "mpo_check_vnode_readlink" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13162 msgid "" "int mpo_check_vnode_readlink " "struct ucred *cred " "struct vnode *vp " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13211 msgid "" "Determine whether the subject credential can perform a readlink operation on the passed symlink vnode. Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatch, or " "EPERM for lack of privilege. This call may be made in " "a number of situations, including an explicit readlink " "call by the user process, or as a result of an implicit readlink during a name lookup by the process." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13225 msgid "mpo_check_vnode_revoke" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13228 msgid "" "int mpo_check_vnode_revoke " "struct ucred *cred " "struct vnode *vp " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13277 msgid "" "Determine whether the subject credential can revoke access to the passed " "vnode. Return 0 for success, or an " "errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13287 msgid "mpo_check_vnode_setacl" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13290 msgid "" "int mpo_check_vnode_setacl " "struct ucred *cred " "struct vnode *vp " "struct label *label " "acl_type_t type struct " "acl *acl" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13346 msgid "acl" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13347 msgid "ACL" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13353 msgid "" "Determine whether the subject credential can set the passed ACL of passed " "type on the passed vnode. Return 0 for success, " "or an errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13363 msgid "mpo_check_vnode_setextattr" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13366 msgid "" "int mpo_check_vnode_setextattr " "struct ucred *cred " "struct vnode *vp " "struct label *label " "int attrnamespace " "const char *name " "struct uio *uio" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13436 msgid "" "Determine whether the subject credential can set the extended attribute of " "passed name and passed namespace on the passed vnode. Policies implementing " "security labels backed into extended attributes may want to provide " "additional protections for those attributes. Additionally, policies should " "avoid making decisions based on the data referenced from uio, as there is a potential race condition between this check and " "the actual operation. The uio may also be " "NULL if a delete operation is being performed. Return " "0 for success, or an errno " "value for failure. Suggested failure: EACCES for " "label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13454 msgid "mpo_check_vnode_setflags" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13457 msgid "" "int mpo_check_vnode_setflags " "struct ucred *cred " "struct vnode *vp " "struct label *label " "u_long flags" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13506 msgid "" "File flags; see chflags2" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13512 msgid "" "Determine whether the subject credential can set the passed flags on the " "passed vnode. Return 0 for success, or an " "errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13522 msgid "mpo_check_vnode_setmode" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13525 msgid "" "int mpo_check_vnode_setmode " "struct ucred *cred " "struct vnode *vp " "struct label *label " "mode_t mode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13573 msgid "mode" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13574 msgid "" "File mode; see chmod2" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13580 msgid "" "Determine whether the subject credential can set the passed mode on the " "passed vnode. Return 0 for success, or an " "errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13590 msgid "mpo_check_vnode_setowner" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13593 msgid "" "int mpo_check_vnode_setowner " "struct ucred *cred " "struct vnode *vp " "struct label *label " "uid_t uid gid_t " "gid" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13642 msgid "uid" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13643 msgid "User ID" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13647 msgid "gid" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13648 msgid "Group ID" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13654 msgid "" "Determine whether the subject credential can set the passed uid and passed " "gid as file uid and file gid on the passed vnode. The IDs may be set to " "(-1) to request no update. Return 0 for success, or an errno value for failure. " "Suggested failure: EACCES for label mismatch, or " "EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13665 msgid "mpo_check_vnode_setutimes" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13668 msgid "" "int mpo_check_vnode_setutimes " "struct ucred *cred struct vnode " "*vp struct label *label struct timespec atime " "struct timespec mtime" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13704 msgid "Object; vp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13714 msgid "atime" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13715 msgid "" "Access time; see utimes2" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13719 msgid "mtime" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13720 msgid "" "Modification time; see utimes2" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13726 msgid "" "Determine whether the subject credential can set the passed access " "timestamps on the passed vnode. Return 0 for " "success, or an errno value for failure. Suggested failure:" " EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13736 msgid "mpo_check_proc_sched" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13739 msgid "" "int mpo_check_proc_sched " "struct ucred *ucred " "struct proc *proc" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13780 msgid "" "Determine whether the subject credential can change the scheduling " "parameters of the passed process. Return 0 for " "success, or an errno value for failure. Suggested failure:" " EACCES for label mismatch, EPERM for lack of privilege, or ESRCH to limit " "visibility." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13788 msgid "" "See setpriority2 for more information." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13792 msgid "mpo_check_proc_signal" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13795 msgid "" "int mpo_check_proc_signal " "struct ucred *cred " "struct proc *proc int " "signal" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13835 msgid "signal" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13836 msgid "" "Signal; see kill2" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13842 msgid "" "Determine whether the subject credential can deliver the passed signal to " "the passed process. Return 0 for success, or an " "errno value for failure. Suggested failure: " "EACCES for label mismatch, EPERM for lack of privilege, or ESRCH to limit " "visibility." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13852 msgid "mpo_check_vnode_stat" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13855 msgid "" "int mpo_check_vnode_stat " "struct ucred *cred " "struct vnode *vp " "struct label *label" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13904 msgid "" "Determine whether the subject credential can stat the " "passed vnode. Return 0 for success, or an " "errno value for failure. Suggested failure: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13912 msgid "" "See stat2 for more information." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13916 msgid "mpo_check_ifnet_transmit" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13919 msgid "" "int mpo_check_ifnet_transmit " "struct ucred *cred " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct mbuf *mbuf " "struct label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:13971 msgid "Object; mbuf to be sent" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:13983 msgid "" "Determine whether the network interface can transmit the passed mbuf. Return " "0 for success, or an errno " "value for failure. Suggested failure: EACCES for " "label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:13992 msgid "mpo_check_socket_deliver" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:13995 msgid "" "int mpo_check_socket_deliver " "struct ucred *cred " "struct ifnet *ifnet " "struct label *ifnetlabel " "struct mbuf *mbuf " "struct label *mbuflabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14047 msgid "Object; mbuf to be delivered" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14059 msgid "" "Determine whether the socket may receive the datagram stored in the passed " "mbuf header. Return 0 for success, or an " "errno value for failure. Suggested failures: " "EACCES for label mismatch, or EPERM for lack of privilege." msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14072 msgid "" "int mpo_check_socket_visible " "struct ucred *cred " "struct socket *so " "struct label *socketlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14115 msgid "Policy label for so" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14122 msgid "" "Determine whether the subject credential cred can \"see\" the passed socket " "(socket) using system monitoring functions, such as " "those employed by netstat8 and " "sockstat1. Return 0 for success, " "or an errno value for failure. Suggested failure: " "EACCES for label mismatches, EPERM for lack of privilege, or ESRCH to hide " "visibility." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14134 msgid "mpo_check_system_acct" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14137 msgid "" "int mpo_check_system_acct " "struct ucred *ucred " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14168 msgid "ucred" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14174 msgid "" "Accounting file; acct5" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14186 msgid "" "Determine whether the subject should be allowed to enable accounting, based " "on its label and the label of the accounting log file." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14192 msgid "mpo_check_system_nfsd" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14195 msgid "" "int mpo_check_system_nfsd " "struct ucred *cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14229 msgid "" "Determine whether the subject should be allowed to call " "nfssvc2." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14234 msgid "mpo_check_system_reboot" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14237 msgid "" "int mpo_check_system_reboot " "struct ucred *cred int " "howto" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14270 msgid "howto" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14271 msgid "" "howto parameter from " "reboot2" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14278 msgid "" "Determine whether the subject should be allowed to reboot the system in the " "specified manner." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14283 msgid "mpo_check_system_settime" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14286 msgid "" "int mpo_check_system_settime " "struct ucred *cred" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14320 msgid "Determine whether the user should be allowed to set the system clock." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14325 msgid "mpo_check_system_swapon" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14328 msgid "" "int mpo_check_system_swapon " "struct ucred *cred " "struct vnode *vp " "struct label *vlabel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14365 msgid "Swap device" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14377 msgid "" "Determine whether the subject should be allowed to add vp as a swap device." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:14382 msgid "mpo_check_system_sysctl" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:14385 msgid "" "int mpo_check_system_sysctl " "struct ucred *cred int " "*name u_int *namelen void *old " "size_t *oldlenp int " "inkernel void *new size_t newlen" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14426 book.translate.xml:14449 msgid "" "See sysctl3" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14438 msgid "oldlenp" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14442 msgid "inkernel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14443 msgid "Boolean; 1 if called from kernel" msgstr "" #. (itstool) path: row/entry #: book.translate.xml:14453 msgid "newlen" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:14459 msgid "" "Determine whether the subject should be allowed to make the specified " "sysctl3 transaction." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:14465 msgid "Label Management Calls" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14467 msgid "" "Relabel events occur when a user process has requested that the label on an " "object be modified. A two-phase update occurs: first, an access control " "check will be performed to determine if the update is both valid and " "permitted, and then the update itself is performed via a separate entry " "point. Relabel entry points typically accept the object, object label " "reference, and an update label submitted by the process. Memory allocation " "during relabel is discouraged, as relabel calls are not permitted to fail " "(failure should be reported earlier in the relabel check)." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14481 msgid "Userland Architecture" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14483 msgid "" "The TrustedBSD MAC Framework includes a number of policy-agnostic elements, " "including MAC library interfaces for abstractly managing labels, " "modifications to the system credential management and login libraries to " "support the assignment of MAC labels to users, and a set of tools to monitor " "and modify labels on processes, files, and network interfaces. More details " "on the user architecture will be added to this section in the near future." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:14493 msgid "APIs for Policy-Agnostic Label Management" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14495 msgid "" "The TrustedBSD MAC Framework provides a number of library and system calls " "permitting applications to manage MAC labels on objects using a policy-" "agnostic interface. This permits applications to manipulate labels for a " "variety of policies without being written to support specific policies. " "These interfaces are used by general-purpose tools such as " "ifconfig8, ls1 and " "ps1 to view labels on network interfaces, files, and processes. " "The APIs also support MAC management tools including " "getfmac8, getpmac8, " "setfmac8, setfsmac8, and " "setpmac8. The MAC APIs are documented in " "mac3." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14509 msgid "" "Applications handle MAC labels in two forms: an internalized form used to " "return and set labels on processes and objects (mac_t), " "and externalized form based on C strings appropriate for storage in " "configuration files, display to the user, or input from the user. Each MAC " "label contains a number of elements, each consisting of a name and value " "pair. Policy modules in the kernel bind to specific names and interpret the " "values in policy-specific ways. In the externalized string form, labels are " "represented by a comma-delimited list of name and value pairs separated by " "the / character. Labels may be directly converted to and " "from text using provided APIs; when retrieving labels from the kernel, " "internalized label storage must first be prepared for the desired label " "element set. Typically, this is done in one of two ways: using " "mac_prepare3 and an arbitrary list of desired label elements, " "or one of the variants of the call that loads a default element set from the " "mac.conf5 configuration file. Per-object defaults permit " "application writers to usefully display labels associated with objects " "without being aware of the policies present in the system." msgstr "" #. (itstool) path: note/para #: book.translate.xml:14534 msgid "" "Currently, direct manipulation of label elements other than by conversion to " "a text string, string editing, and conversion back to an internalized label " "is not supported by the MAC library. Such interfaces may be added in the " "future if they prove necessary for application writers." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:14544 msgid "Binding of Labels to Users" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14546 msgid "" "The standard user context management interface, " "setusercontext3, has been modified to retrieve MAC labels " "associated with a user's class from login.conf5. These labels are then " "set along with other user context when either LOGIN_SETALL is specified, or when LOGIN_SETMAC is explicitly " "specified." msgstr "" #. (itstool) path: note/para #: book.translate.xml:14555 msgid "" "It is expected that, in a future version of FreeBSD, the MAC label database " "will be separated from the login.conf user class " "abstraction, and be maintained in a separate database. However, the " "setusercontext3 API should remain the same following such a change." "" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14565 msgid "Conclusion" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14567 msgid "" "The TrustedBSD MAC framework permits kernel modules to augment the system " "security policy in a highly integrated manner. They may do this based on " "existing object properties, or based on label data that is maintained with " "the assistance of the MAC framework. The framework is sufficiently flexible " "to implement a variety of policy types, including information flow security " "policies such as MLS and Biba, as well as policies based on existing BSD " "credentials or file protections. Policy authors may wish to consult this " "documentation as well as existing security modules when implementing a new " "security service." msgstr "" #. (itstool) path: info/title #: book.translate.xml:14590 msgid "Virtual Memory System" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:14593 msgid "" " Matthew Dillon Contributed by " msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14604 msgid "Management of Physical Memory—vm_page_t" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14607 msgid "virtual memory" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14608 msgid "physical memory" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14609 msgid "vm_page_t structure" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14613 msgid "" "Physical memory is managed on a page-by-page basis through the " "vm_page_t structure. Pages of physical memory are " "categorized through the placement of their respective vm_page_t structures on one of several paging queues." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14619 msgid "" "A page can be in a wired, active, inactive, cache, or free state. Except for " "the wired state, the page is typically placed in a doubly link list queue " "representing the state that it is in. Wired pages are not placed on any " "queue." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14624 msgid "" "FreeBSD implements a more involved paging queue for cached and free pages in " "order to implement page coloring. Each of these states involves multiple " "queues arranged according to the size of the processor's L1 and L2 caches. " "When a new page needs to be allocated, FreeBSD attempts to obtain one that " "is reasonably well aligned from the point of view of the L1 and L2 caches " "relative to the VM object the page is being allocated for." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14633 msgid "" "Additionally, a page may be held with a reference count or locked with a " "busy count. The VM system also implements an ultimate locked " "state for a page using the PG_BUSY bit in the page's flags." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14638 msgid "" "In general terms, each of the paging queues operates in a LRU fashion. A " "page is typically placed in a wired or active state initially. When wired, " "the page is usually associated with a page table somewhere. The VM system " "ages the page by scanning pages in a more active paging queue (LRU) in order " "to move them to a less-active paging queue. Pages that get moved into the " "cache are still associated with a VM object but are candidates for immediate " "reuse. Pages in the free queue are truly free. FreeBSD attempts to minimize " "the number of pages in the free queue, but a certain minimum number of truly " "free pages must be maintained in order to accommodate page allocation at " "interrupt time." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14651 msgid "" "If a process attempts to access a page that does not exist in its page table " "but does exist in one of the paging queues (such as the inactive or cache " "queues), a relatively inexpensive page reactivation fault occurs which " "causes the page to be reactivated. If the page does not exist in system " "memory at all, the process must block while the page is brought in from disk." "" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14659 msgid "paging queues" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14661 msgid "" "FreeBSD dynamically tunes its paging queues and attempts to maintain " "reasonable ratios of pages in the various queues as well as attempts to " "maintain a reasonable breakdown of clean versus dirty pages. The amount of " "rebalancing that occurs depends on the system's memory load. This " "rebalancing is implemented by the pageout daemon and involves laundering " "dirty pages (syncing them with their backing store), noticing when pages are " "activity referenced (resetting their position in the LRU queues or moving " "them between queues), migrating pages between queues when the queues are out " "of balance, and so forth. FreeBSD's VM system is willing to take a " "reasonable number of reactivation page faults to determine how active or how " "idle a page actually is. This leads to better decisions being made as to " "when to launder or swap-out a page." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14678 msgid "The Unified Buffer Cache—vm_object_t" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14681 msgid "unified buffer cache" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14682 msgid "vm_object_t structure" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14686 msgid "" "FreeBSD implements the idea of a generic VM object. VM " "objects can be associated with backing store of various types—unbacked, swap-" "backed, physical device-backed, or file-backed storage. Since the filesystem " "uses the same VM objects to manage in-core data relating to files, the " "result is a unified buffer cache." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14693 msgid "" "VM objects can be shadowed. That is, they can be " "stacked on top of each other. For example, you might have a swap-backed VM " "object stacked on top of a file-backed VM object in order to implement a " "MAP_PRIVATE mmap()ing. This stacking is also used to implement various " "sharing properties, including copy-on-write, for forked address spaces." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14701 msgid "" "It should be noted that a vm_page_t can only be " "associated with one VM object at a time. The VM object shadowing implements " "the perceived sharing of the same page across multiple instances." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14708 msgid "Filesystem I/O—struct buf" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14710 msgid "vnode" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14711 msgid "" "vnode-backed VM objects, such as file-backed objects, generally need to " "maintain their own clean/dirty info independent from the VM system's idea of " "clean/dirty. For example, when the VM system decides to synchronize a " "physical page to its backing store, the VM system needs to mark the page " "clean before the page is actually written to its backing store. " "Additionally, filesystems need to be able to map portions of a file or file " "metadata into KVM in order to operate on it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14720 msgid "" "The entities used to manage this are known as filesystem buffers, " "struct buf's, or bp's. When a " "filesystem needs to operate on a portion of a VM object, it typically maps " "part of the object into a struct buf and then maps the pages in the struct " "buf into KVM. In the same manner, disk I/O is typically issued by mapping " "portions of objects into buffer structures and then issuing the I/O on the " "buffer structures. The underlying vm_page_t's are typically busied for the " "duration of the I/O. Filesystem buffers also have their own notion of being " "busy, which is useful to filesystem driver code which would rather operate " "on filesystem buffers instead of hard VM pages." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14733 msgid "" "FreeBSD reserves a limited amount of KVM to hold mappings from struct bufs, " "but it should be made clear that this KVM is used solely to hold mappings " "and does not limit the ability to cache data. Physical data caching is " "strictly a function of vm_page_t's, not filesystem " "buffers. However, since filesystem buffers are used to placehold I/O, they " "do inherently limit the amount of concurrent I/O possible. However, as there " "are usually a few thousand filesystem buffers available, this is not usually " "a problem." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14745 msgid "Mapping Page Tables—vm_map_t, vm_entry_t" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14748 msgid "page tables" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14749 msgid "" "FreeBSD separates the physical page table topology from the VM system. All " "hard per-process page tables can be reconstructed on the fly and are usually " "considered throwaway. Special page tables such as those managing KVM are " "typically permanently preallocated. These page tables are not throwaway." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14756 msgid "" "FreeBSD associates portions of vm_objects with address ranges in virtual " "memory through vm_map_t and vm_entry_t " "structures. Page tables are directly synthesized from the vm_map_t/vm_entry_t/ vm_object_t " "hierarchy. Recall that I mentioned that physical pages are only directly " "associated with a vm_object; that is not quite true. " "vm_page_t's are also linked into page tables that they " "are actively associated with. One vm_page_t can be linked " "into several pmaps, as page tables are called. However, " "the hierarchical association holds, so all references to the same page in " "the same object reference the same vm_page_t and thus " "give us buffer cache unification across the board." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14775 msgid "KVM Memory Mapping" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14777 msgid "" "FreeBSD uses KVM to hold various kernel structures. The single largest " "entity held in KVM is the filesystem buffer cache. That is, mappings " "relating to struct buf entities." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14782 msgid "" "Unlike Linux, FreeBSD does not map all of physical " "memory into KVM. This means that FreeBSD can handle memory configurations up " "to 4G on 32 bit platforms. In fact, if the mmu were capable of it, FreeBSD " "could theoretically handle memory configurations up to 8TB on a 32 bit " "platform. However, since most 32 bit platforms are only capable of mapping " "4GB of ram, this is a moot point." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14790 msgid "" "KVM is managed through several mechanisms. The main mechanism used to manage " "KVM is the zone allocator. The zone allocator takes a " "chunk of KVM and splits it up into constant-sized blocks of memory in order " "to allocate a specific type of structure. You can use vmstat -m to get an overview of current KVM utilization broken down by zone." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14800 msgid "Tuning the FreeBSD VM System" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14802 msgid "" "A concerted effort has been made to make the FreeBSD kernel dynamically tune " "itself. Typically you do not need to mess with anything beyond the " " and kernel config " "options. That is, kernel compilation options specified in (typically) " "/usr/src/sys/i386/conf/CONFIG_FILE. A description of all available kernel configuration options can " "be found in /usr/src/sys/i386/conf/LINT." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14812 msgid "" "In a large system configuration you may wish to increase too high can cause the system to overflow " "available KVM resulting in unpredictable operation. It is better to leave " " at some reasonable number and add other options, " "such as , to increase specific resources." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14821 msgid "" "If your system is going to use the network heavily, you may want to increase " ". Typical values range from 1024 to 4096." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14825 msgid "" "The NBUF parameter is also traditionally used to scale " "the system. This parameter determines the amount of KVA the system can use " "to map filesystem buffers for I/O. Note that this parameter has nothing " "whatsoever to do with the unified buffer cache! This parameter is " "dynamically tuned in 3.0-CURRENT and later kernels and should generally not " "be adjusted manually. We recommend that you not try to " "specify an NBUF parameter. Let the system pick it. Too " "small a value can result in extremely inefficient filesystem operation while " "too large a value can starve the page queues by causing too many pages to " "become wired down." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14838 msgid "" "By default, FreeBSD kernels are not optimized. You can set debugging and " "optimization flags with the makeoptions directive in the " "kernel configuration. Note that you should not use " "unless you can accommodate the large (typically 7 MB+) kernels that result." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:14845 #, no-wrap msgid "makeoptions DEBUG=\"-g\"\n" "makeoptions COPTFLAGS=\"-O -pipe\"" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14848 msgid "" "Sysctl provides a way to tune kernel parameters at run-time. You typically " "do not need to mess with any of the sysctl variables, especially the VM " "related ones." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14852 msgid "" "Run time VM and system tuning is relatively straightforward. First, use Soft " "Updates on your UFS/FFS filesystems whenever possible. /usr/src/" "sys/ufs/ffs/README.softupdates contains instructions (and " "restrictions) on how to configure it." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14859 msgid "swap partition" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14860 msgid "" "Second, configure sufficient swap. You should have a swap partition " "configured on each physical disk, up to four, even on your work disks. You should have at least 2x the swap space as you have main " "memory, and possibly even more if you do not have a lot of memory. You " "should also size your swap partition based on the maximum memory " "configuration you ever intend to put on the machine so you do not have to " "repartition your disks later on. If you want to be able to accommodate a " "crash dump, your first swap partition must be at least as large as main " "memory and /var/crash must have sufficient free space " "to hold the dump." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14872 msgid "" "NFS-based swap is perfectly acceptable on 4.X or later systems, but you must " "be aware that the NFS server will take the brunt of the paging load." msgstr "" #. (itstool) path: info/title #: book.translate.xml:14886 msgid "SMPng Design Document" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:14888 msgid "" "JohnBaldwinWritten by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:14889 msgid "" "RobertWatson" msgstr "" #. (itstool) path: info/copyright #: book.translate.xml:14892 msgid "" "2002 2004 2005 John Baldwin Robert Watson" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14906 msgid "SMP Next Generation" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14907 msgid "kernel synchronization" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14909 msgid "" "This document presents the current design and implementation of the SMPng " "Architecture. First, the basic primitives and tools are introduced. Next, a " "general architecture for the FreeBSD kernel's synchronization and execution " "model is laid out. Then, locking strategies for specific subsystems are " "discussed, documenting the approaches taken to introduce fine-grained " "synchronization and parallelism for each subsystem. Finally, detailed " "implementation notes are provided to motivate design choices, and make the " "reader aware of important implications involving the use of specific " "primitives." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14920 msgid "" "This document is a work-in-progress, and will be updated to reflect on-going " "design and implementation activities associated with the SMPng Project. Many " "sections currently exist only in outline form, but will be fleshed out as " "work proceeds. Updates or suggestions regarding the document may be directed " "to the document editors." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:14927 msgid "concurrency" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:14928 msgid "" "The goal of SMPng is to allow concurrency in the kernel. The kernel is " "basically one rather large and complex program. To make the kernel multi-" "threaded we use some of the same tools used to make other programs multi-" "threaded. These include mutexes, shared/exclusive locks, semaphores, and " "condition variables. For the definitions of these and other SMP-related " "terms, please see the section of this " "article." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:14938 msgid "Basic Tools and Locking Fundamentals" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:14941 msgid "Atomic Instructions and Memory Barriers" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:14943 msgid "atomic instructions" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:14944 msgid "memory barriers" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14946 msgid "" "There are several existing treatments of memory barriers and atomic " "instructions, so this section will not include a lot of detail. To put it " "simply, one can not go around reading variables without a lock if a lock is " "used to protect writes to that variable. This becomes obvious when you " "consider that memory barriers simply determine relative order of memory " "operations; they do not make any guarantee about timing of memory operations." " That is, a memory barrier does not force the contents of a CPU's local " "cache or store buffer to flush. Instead, the memory barrier at lock release " "simply ensures that all writes to the protected data will be visible to " "other CPU's or devices if the write to release the lock is visible. The CPU " "is free to keep that data in its cache or store buffer as long as it wants. " "However, if another CPU performs an atomic instruction on the same datum, " "the first CPU must guarantee that the updated value is made visible to the " "second CPU along with any other operations that memory barriers may require." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14965 msgid "" "For example, assuming a simple model where data is considered visible when " "it is in main memory (or a global cache), when an atomic instruction is " "triggered on one CPU, other CPU's store buffers and caches must flush any " "writes to that same cache line along with any pending operations behind a " "memory barrier." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14972 msgid "" "This requires one to take special care when using an item protected by " "atomic instructions. For example, in the sleep mutex implementation, we have " "to use an atomic_cmpset rather than an " "atomic_set to turn on the MTX_CONTESTED bit. The reason is that we read the value of mtx_lock into a variable and then make a decision " "based on that read. However, the value we read may be stale, or it may " "change while we are making our decision. Thus, when the " "atomic_set executed, it may end up setting the bit on " "another value than the one we made the decision on. Thus, we have to use an " "atomic_cmpset to set the value only if the value we " "made the decision on is up-to-date and valid." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:14989 msgid "" "Finally, atomic instructions only allow one item to be updated or read. If " "one needs to atomically update several items, then a lock must be used " "instead. For example, if two counters must be read and have values that are " "consistent relative to each other, then those counters must be protected by " "a lock rather than by separate atomic instructions." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:14998 msgid "Read Locks Versus Write Locks" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15000 msgid "read locks" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15001 msgid "write locks" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15002 msgid "" "Read locks do not need to be as strong as write locks. Both types of locks " "need to ensure that the data they are accessing is not stale. However, only " "write access requires exclusive access. Multiple threads can safely read a " "value. Using different types of locks for reads and writes can be " "implemented in a number of ways." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15009 msgid "" "First, sx locks can be used in this manner by using an exclusive lock when " "writing and a shared lock when reading. This method is quite straightforward." "" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15013 msgid "" "A second method is a bit more obscure. You can protect a datum with multiple " "locks. Then for reading that data you simply need to have a read lock of one " "of the locks. However, to write to the data, you need to have a write lock " "of all of the locks. This can make writing rather expensive but can be " "useful when data is accessed in various ways. For example, the parent " "process pointer is protected by both the proctree_lock sx " "lock and the per-process mutex. Sometimes the proc lock is easier as we are " "just checking to see who a parent of a process is that we already have " "locked. However, other places such as inferior need to " "walk the tree of processes via parent pointers and locking each process " "would be prohibitive as well as a pain to guarantee that the condition you " "are checking remains valid for both the check and the actions taken as a " "result of the check." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15032 msgid "Locking Conditions and Results" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15034 msgid "" "If you need a lock to check the state of a variable so that you can take an " "action based on the state you read, you can not just hold the lock while " "reading the variable and then drop the lock before you act on the value you " "read. Once you drop the lock, the variable can change rendering your " "decision invalid. Thus, you must hold the lock both while reading the " "variable and while performing the action as a result of the test." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:15046 msgid "General Architecture and Design" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15049 msgid "Interrupt Handling" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15051 msgid "interrupt handling" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15053 msgid "" "Following the pattern of several other multi-threaded UNIX kernels, FreeBSD deals with interrupt " "handlers by giving them their own thread context. Providing a context for " "interrupt handlers allows them to block on locks. To help avoid latency, " "however, interrupt threads run at real-time kernel priority. Thus, interrupt " "handlers should not execute for very long to avoid starving other kernel " "threads. In addition, since multiple handlers may share an interrupt thread, " "interrupt handlers should not sleep or use a sleepable lock to avoid " "starving another interrupt handler." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15064 msgid "interrupt threads" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15066 msgid "" "The interrupt threads currently in FreeBSD are referred to as heavyweight " "interrupt threads. They are called this because switching to an interrupt " "thread involves a full context switch. In the initial implementation, the " "kernel was not preemptive and thus interrupts that interrupted a kernel " "thread would have to wait until the kernel thread blocked or returned to " "userland before they would have an opportunity to run." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15075 msgid "latency" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15076 msgid "preemption" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15078 msgid "" "To deal with the latency problems, the kernel in FreeBSD has been made " "preemptive. Currently, we only preempt a kernel thread when we release a " "sleep mutex or when an interrupt comes in. However, the plan is to make the " "FreeBSD kernel fully preemptive as described below." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15084 msgid "" "Not all interrupt handlers execute in a thread context. Instead, some " "handlers execute directly in primary interrupt context. These interrupt " "handlers are currently misnamed fast interrupt handlers since " "the INTR_FAST flag used in earlier versions of the " "kernel is used to mark these handlers. The only interrupts which currently " "use these types of interrupt handlers are clock interrupts and serial I/O " "device interrupts. Since these handlers do not have their own context, they " "may not acquire blocking locks and thus may only use spin mutexes." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15096 msgid "context switches" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15098 msgid "" "Finally, there is one optional optimization that can be added in MD code " "called lightweight context switches. Since an interrupt thread executes in a " "kernel context, it can borrow the vmspace of any process. Thus, in a " "lightweight context switch, the switch to the interrupt thread does not " "switch vmspaces but borrows the vmspace of the interrupted thread. In order " "to ensure that the vmspace of the interrupted thread does not disappear out " "from under us, the interrupted thread is not allowed to execute until the " "interrupt thread is no longer borrowing its vmspace. This can happen when " "the interrupt thread either blocks or finishes. If an interrupt thread " "blocks, then it will use its own context when it is made runnable again. " "Thus, it can release the interrupted thread." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15113 msgid "" "The cons of this optimization are that they are very machine specific and " "complex and thus only worth the effort if their is a large performance " "improvement. At this point it is probably too early to tell, and in fact, " "will probably hurt performance as almost all interrupt handlers will " "immediately block on Giant and require a thread fix-up when they block. " "Also, an alternative method of interrupt handling has been proposed by Mike " "Smith that works like so:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:15124 msgid "" "Each interrupt handler has two parts: a predicate which runs in primary " "interrupt context and a handler which runs in its own thread context." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:15130 msgid "" "If an interrupt handler has a predicate, then when an interrupt is " "triggered, the predicate is run. If the predicate returns true then the " "interrupt is assumed to be fully handled and the kernel returns from the " "interrupt. If the predicate returns false or there is no predicate, then the " "threaded handler is scheduled to run." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15139 msgid "" "Fitting light weight context switches into this scheme might prove rather " "complicated. Since we may want to change to this scheme at some point in the " "future, it is probably best to defer work on light weight context switches " "until we have settled on the final interrupt handling architecture and " "determined how light weight context switches might or might not fit into it." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15149 msgid "Kernel Preemption and Critical Sections" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:15152 msgid "Kernel Preemption in a Nutshell" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15154 msgid "" "Kernel preemption is fairly simple. The basic idea is that a CPU should " "always be doing the highest priority work available. Well, that is the ideal " "at least. There are a couple of cases where the expense of achieving the " "ideal is not worth being perfect." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15160 msgid "" "Implementing full kernel preemption is very straightforward: when you " "schedule a thread to be executed by putting it on a run queue, you check to " "see if its priority is higher than the currently executing thread. If so, " "you initiate a context switch to that thread." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15166 msgid "" "While locks can protect most data in the case of a preemption, not all of " "the kernel is preemption safe. For example, if a thread holding a spin mutex " "preempted and the new thread attempts to grab the same spin mutex, the new " "thread may spin forever as the interrupted thread may never get a chance to " "execute. Also, some code such as the code to assign an address space number " "for a process during exec on the Alpha needs to not be " "preempted as it supports the actual context switch code. Preemption is " "disabled for these code sections by using a critical section." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:15180 msgid "Critical Sections" msgstr "" #. (itstool) path: sect3/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:15182 book.translate.xml:15304 msgid "critical sections" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15184 msgid "" "The responsibility of the critical section API is to prevent context " "switches inside of a critical section. With a fully preemptive kernel, every " "setrunqueue of a thread other than the current thread " "is a preemption point. One implementation is for critical_enter to set a per-thread flag that is cleared by its counterpart. If " "setrunqueue is called with this flag set, it does not " "preempt regardless of the priority of the new thread relative to the current " "thread. However, since critical sections are used in spin mutexes to prevent " "context switches and multiple spin mutexes can be acquired, the critical " "section API must support nesting. For this reason the current implementation " "uses a nesting count instead of a single per-thread flag." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15200 msgid "" "In order to minimize latency, preemptions inside of a critical section are " "deferred rather than dropped. If a thread that would normally be preempted " "to is made runnable while the current thread is in a critical section, then " "a per-thread flag is set to indicate that there is a pending preemption. " "When the outermost critical section is exited, the flag is checked. If the " "flag is set, then the current thread is preempted to allow the higher " "priority thread to run." msgstr "" #. (itstool) path: sect3/indexterm #: book.translate.xml:15210 msgid "spin mutexes" msgstr "" #. (itstool) path: sect3/indexterm #: book.translate.xml:15211 msgid "mutexesspin" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15212 msgid "" "Interrupts pose a problem with regards to spin mutexes. If a low-level " "interrupt handler needs a lock, it needs to not interrupt any code needing " "that lock to avoid possible data structure corruption. Currently, providing " "this mechanism is piggybacked onto critical section API by means of the " "cpu_critical_enter and cpu_critical_exit functions. Currently this API disables and re-enables interrupts " "on all of FreeBSD's current platforms. This approach may not be purely " "optimal, but it is simple to understand and simple to get right. " "Theoretically, this second API need only be used for spin mutexes that are " "used in primary interrupt context. However, to make the code simpler, it is " "used for all spin mutexes and even all critical sections. It may be " "desirable to split out the MD API from the MI API and only use it in " "conjunction with the MI API in the spin mutex implementation. If this " "approach is taken, then the MD API likely would need a rename to show that " "it is a separate API." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:15234 msgid "Design Tradeoffs" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15236 msgid "" "As mentioned earlier, a couple of trade-offs have been made to sacrifice " "cases where perfect preemption may not always provide the best performance." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15240 msgid "" "The first trade-off is that the preemption code does not take other CPUs " "into account. Suppose we have a two CPU's A and B with the priority of A's " "thread as 4 and the priority of B's thread as 2. If CPU B makes a thread " "with priority 1 runnable, then in theory, we want CPU A to switch to the new " "thread so that we will be running the two highest priority runnable threads. " "However, the cost of determining which CPU to enforce a preemption on as " "well as actually signaling that CPU via an IPI along with the " "synchronization that would be required would be enormous. Thus, the current " "code would instead force CPU B to switch to the higher priority thread. Note " "that this still puts the system in a better position as CPU B is executing a " "thread of priority 1 rather than a thread of priority 2." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15255 msgid "" "The second trade-off limits immediate kernel preemption to real-time " "priority kernel threads. In the simple case of preemption defined above, a " "thread is always preempted immediately (or as soon as a critical section is " "exited) if a higher priority thread is made runnable. However, many threads " "executing in the kernel only execute in a kernel context for a short time " "before either blocking or returning to userland. Thus, if the kernel " "preempts these threads to run another non-realtime kernel thread, the kernel " "may switch out the executing thread just before it is about to sleep or " "execute. The cache on the CPU must then adjust to the new thread. When the " "kernel returns to the preempted thread, it must refill all the cache " "information that was lost. In addition, two extra context switches are " "performed that could be avoided if the kernel deferred the preemption until " "the first thread blocked or returned to userland. Thus, by default, the " "preemption code will only preempt immediately if the higher priority thread " "is a real-time priority thread." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15275 msgid "" "Turning on full kernel preemption for all kernel threads has value as a " "debugging aid since it exposes more race conditions. It is especially useful " "on UP systems were many races are hard to simulate otherwise. Thus, there is " "a kernel option FULL_PREEMPTION to enable preemption for " "all kernel threads that can be used for debugging purposes." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15286 msgid "Thread Migration" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15288 msgid "thread migration" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15290 msgid "" "Simply put, a thread migrates when it moves from one CPU to another. In a " "non-preemptive kernel this can only happen at well-defined points such as " "when calling msleep or returning to userland. However, " "in the preemptive kernel, an interrupt can force a preemption and possible " "migration at any time. This can have negative affects on per-CPU data since " "with the exception of curthread and curpcb the data can change whenever you migrate. Since you can potentially " "migrate at any time this renders unprotected per-CPU data access rather " "useless. Thus it is desirable to be able to disable migration for sections " "of code that need per-CPU data to be stable." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15306 msgid "" "Critical sections currently prevent migration since they do not allow " "context switches. However, this may be too strong of a requirement to " "enforce in some cases since a critical section also effectively blocks " "interrupt threads on the current processor. As a result, another API has " "been provided to allow the current thread to indicate that if it preempted " "it should not migrate to another CPU." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15314 msgid "" "This API is known as thread pinning and is provided by the scheduler. The " "API consists of two functions: sched_pin and " "sched_unpin. These functions manage a per-thread " "nesting count td_pinned. A thread is pinned when its " "nesting count is greater than zero and a thread starts off unpinned with a " "nesting count of zero. Each scheduler implementation is required to ensure " "that pinned threads are only executed on the CPU that they were executing on " "when the sched_pin was first called. Since the nesting " "count is only written to by the thread itself and is only read by other " "threads when the pinned thread is not executing but while " "sched_lock is held, then td_pinned " "does not need any locking. The sched_pin function " "increments the nesting count and sched_unpin decrements " "the nesting count. Note that these functions only operate on the current " "thread and bind the current thread to the CPU it is executing on at the time." " To bind an arbitrary thread to a specific CPU, the sched_bind and sched_unbind functions should be used " "instead." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15340 msgid "Callouts" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15342 msgid "" "The timeout kernel facility permits kernel services to " "register functions for execution as part of the softclock software interrupt. Events are scheduled based on a desired number " "of clock ticks, and callbacks to the consumer-provided function will occur " "at approximately the right time." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15349 msgid "" "The global list of pending timeout events is protected by a global spin " "mutex, callout_lock; all access to the timeout list must " "be performed with this mutex held. When softclock is " "woken up, it scans the list of pending timeouts for those that should fire. " "In order to avoid lock order reversal, the softclock " "thread will release the callout_lock mutex when invoking " "the provided timeout callback function. If the " "CALLOUT_MPSAFE flag was not set during registration, " "then Giant will be grabbed before invoking the callout, and then released " "afterwards. The callout_lock mutex will be re-grabbed " "before proceeding. The softclock code is careful to " "leave the list in a consistent state while releasing the mutex. If " "DIAGNOSTIC is enabled, then the time taken to execute " "each function is measured, and a warning is generated if it exceeds a " "threshold." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:15372 msgid "Specific Locking Strategies" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15375 msgid "Credentials" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15377 msgid "credentials" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15379 msgid "" "struct ucred is the kernel's " "internal credential structure, and is generally used as the basis for " "process-driven access control within the kernel. BSD-derived systems use a " "copy-on-write model for credential data: multiple references " "may exist for a credential structure, and when a change needs to be made, " "the structure is duplicated, modified, and then the reference replaced. Due " "to wide-spread caching of the credential to implement access control on " "open, this results in substantial memory savings. With a move to fine-" "grained SMP, this model also saves substantially on locking operations by " "requiring that modification only occur on an unshared credential, avoiding " "the need for explicit synchronization when consuming a known-shared " "credential." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15394 msgid "" "Credential structures with a single reference are considered mutable; shared " "credential structures must not be modified or a race condition is risked. A " "mutex, cr_mtxp protects the " "reference count of struct ucred so " "as to maintain consistency. Any use of the structure requires a valid " "reference for the duration of the use, or the structure may be released out " "from under the illegitimate consumer." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15404 msgid "" "The struct ucred mutex is a leaf " "mutex and is implemented via a mutex pool for performance reasons." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15408 msgid "" "Usually, credentials are used in a read-only manner for access control " "decisions, and in this case td_ucred is generally preferred because it requires no locking. When a " "process' credential is updated the proc lock must be held " "across the check and update operations thus avoid races. The process " "credential p_ucred must be used for " "check and update operations to prevent time-of-check, time-of-use races." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15418 msgid "" "If system call invocations will perform access control after an update to " "the process credential, the value of td_ucred must also be refreshed to the current " "process value. This will prevent use of a stale credential following a " "change. The kernel automatically refreshes the td_ucred pointer in the thread structure from the " "process p_ucred whenever a process " "enters the kernel, permitting use of a fresh credential for kernel access " "control." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15431 msgid "File Descriptors and File Descriptor Tables" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15433 msgid "Details to follow." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15437 msgid "Jail Structures" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15441 msgid "" "struct prison stores administrative " "details pertinent to the maintenance of jails created using the " "jail2 API. This includes the per-jail hostname, IP address, and " "related settings. This structure is reference-counted since pointers to " "instances of the structure are shared by many credential structures. A " "single mutex, pr_mtx protects read " "and write access to the reference count and all mutable variables inside the " "struct jail. Some variables are set only when the jail is created, and a " "valid reference to the struct prison " "is sufficient to read these values. The precise locking of each entry is " "documented via comments in sys/jail.h." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15457 msgid "MAC Framework" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15459 msgid "MAC" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15461 msgid "" "The TrustedBSD MAC Framework maintains data in a variety of kernel objects, " "in the form of struct label. In " "general, labels in kernel objects are protected by the same lock as the " "remainder of the kernel object. For example, the v_label label in struct vnode is protected by the vnode lock on the " "vnode." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15469 msgid "" "In addition to labels maintained in standard kernel objects, the MAC " "Framework also maintains a list of registered and active policies. The " "policy list is protected by a global mutex (mac_policy_list_lock) and a busy count (also protected by the mutex). Since many access " "control checks may occur in parallel, entry to the framework for a read-only " "access to the policy list requires holding the mutex while incrementing (and " "later decrementing) the busy count. The mutex need not be held for the " "duration of the MAC entry operation--some operations, such as label " "operations on file system objects--are long-lived. To modify the policy " "list, such as during policy registration and de-registration, the mutex must " "be held and the reference count must be zero, to prevent modification of the " "list while it is in use." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15484 msgid "" "A condition variable, mac_policy_list_not_busy, is " "available to threads that need to wait for the list to become unbusy, but " "this condition variable must only be waited on if the caller is holding no " "other locks, or a lock order violation may be possible. The busy count, in " "effect, acts as a form of shared/exclusive lock over access to the framework:" " the difference is that, unlike with an sx lock, consumers waiting for the " "list to become unbusy may be starved, rather than permitting lock order " "problems with regards to the busy count and other locks that may be held on " "entry to (or inside) the MAC Framework." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15498 msgid "Modules" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15502 msgid "" "For the module subsystem there exists a single lock that is used to protect " "the shared data. This lock is a shared/exclusive (SX) lock and has a good " "chance of needing to be acquired (shared or exclusively), therefore there " "are a few macros that have been added to make access to the lock more easy. " "These macros can be located in sys/module.h and are " "quite basic in terms of usage. The main structures protected under this lock " "are the module_t structures (when " "shared) and the global modulelist_t " "structure, modules. One should review the related source code in " "kern/kern_module.c to further understand the locking " "strategy." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15517 msgid "Newbus Device Tree" msgstr "" #. (itstool) path: sect2/indexterm #. (itstool) path: sect1/indexterm #: book.translate.xml:15519 book.translate.xml:22509 msgid "Newbus" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15521 msgid "" "The newbus system will have one sx lock. Readers will hold a shared (read) " "lock (sx_slock9) and writers will hold an exclusive (write) lock " "(sx_xlock9). Internal functions will not do locking at all. " "Externally visible ones will lock as needed. Those items that do not matter " "if the race is won or lost will not be locked, since they tend to be read " "all over the place (e.g., device_get_softc9). There will be " "relatively few changes to the newbus data structures, so a single lock " "should be sufficient and not impose a performance penalty." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15534 msgid "Pipes" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15536 book.translate.xml:15569 msgid "..." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15540 msgid "Processes and Threads" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15542 msgid "- process hierarchy" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15543 msgid "- proc locks, references" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15544 msgid "" "- thread-specific copies of proc entries to freeze during system calls, " "including td_ucred" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15546 msgid "- inter-process operations" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15547 msgid "- process groups and sessions" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15551 msgid "Scheduler" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15553 msgid "scheduler" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15555 msgid "" "Lots of references to sched_lock and notes pointing at " "specific primitives and related magic elsewhere in the document." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15561 msgid "Select and Poll" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15563 msgid "" "The select and poll functions " "permit threads to block waiting on events on file descriptors--most " "frequently, whether or not the file descriptors are readable or writable." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15573 msgid "SIGIO" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15575 msgid "" "The SIGIO service permits processes to request the delivery of a SIGIO " "signal to its process group when the read/write status of specified file " "descriptors changes. At most one process or process group is permitted to " "register for SIGIO from any given kernel object, and that process or group " "is referred to as the owner. Each object supporting SIGIO registration " "contains pointer field that is NULL if the object is " "not registered, or points to a struct sigio describing the registration. This field is protected by a global " "mutex, sigio_lock. Callers to SIGIO maintenance functions " "must pass in this field by reference so that local register " "copies of the field are not made when unprotected by the lock." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15590 msgid "" "One struct sigio is allocated for " "each registered object associated with any process or process group, and " "contains back-pointers to the object, owner, signal information, a " "credential, and the general disposition of the registration. Each process or " "progress group contains a list of registered struct sigio structures, p_sigiolst for processes, and pg_sigiolst for process groups. These lists are " "protected by the process or process group locks respectively. Most fields in " "each struct sigio are constant for " "the duration of the registration, with the exception of the sio_pgsigio field which links the struct sigio into the process or process group list." " Developers implementing new kernel objects supporting SIGIO will, in " "general, want to avoid holding structure locks while invoking SIGIO " "supporting functions, such as fsetown or " "funsetown to avoid defining a lock order between " "structure locks and the global SIGIO lock. This is generally possible " "through use of an elevated reference count on the structure, such as " "reliance on a file descriptor reference to a pipe during a pipe operation." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15617 msgid "Sysctl" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15619 msgid "" "The sysctl MIB service is invoked from both within the " "kernel and from userland applications using a system call. At least two " "issues are raised in locking: first, the protection of the structures " "maintaining the namespace, and second, interactions with kernel variables " "and functions that are accessed by the sysctl interface. Since sysctl " "permits the direct export (and modification) of kernel statistics and " "configuration parameters, the sysctl mechanism must become aware of " "appropriate locking semantics for those variables. Currently, sysctl makes " "use of a single global sx lock to serialize use of sysctl; however, it is assumed to operate under Giant and other " "protections are not provided. The remainder of this section speculates on " "locking and semantic changes to sysctl." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15635 msgid "" "- Need to change the order of operations for sysctl's that update values " "from read old, copyin and copyout, write new to copyin, lock, read old and " "write new, unlock, copyout. Normal sysctl's that just copyout the old value " "and set a new value that they copyin may still be able to follow the old " "model. However, it may be cleaner to use the second model for all of the " "sysctl handlers to avoid lock operations." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15643 msgid "" "- To allow for the common case, a sysctl could embed a pointer to a mutex in " "the SYSCTL_FOO macros and in the struct. This would work for most sysctl's. " "For values protected by sx locks, spin mutexes, or other locking strategies " "besides a single sleep mutex, SYSCTL_PROC nodes could be used to get the " "locking right." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15652 msgid "Taskqueue" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15654 msgid "" "The taskqueue's interface has two basic locks associated with it in order to " "protect the related shared data. The taskqueue_queues_mutex is meant to serve as a lock to protect the " "taskqueue_queues TAILQ. The other mutex lock associated " "with this system is the one in the struct " "taskqueue data structure. The use of the synchronization primitive " "here is to protect the integrity of the data in the struct taskqueue. It should be noted that there are " "no separate macros to assist the user in locking down his/her own work since " "these locks are most likely not going to be used outside of kern/" "subr_taskqueue.c." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:15670 msgid "Implementation Notes" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15673 msgid "Sleep Queues" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15675 msgid "" "A sleep queue is a structure that holds the list of threads asleep on a wait " "channel. Each thread that is not asleep on a wait channel carries a sleep " "queue structure around with it. When a thread blocks on a wait channel, it " "donates its sleep queue structure to that wait channel. Sleep queues " "associated with a wait channel are stored in a hash table." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15683 msgid "" "The sleep queue hash table holds sleep queues for wait channels that have at " "least one blocked thread. Each entry in the hash table is called a " "sleepqueue chain. The chain contains a linked list of sleep queues and a " "spin mutex. The spin mutex protects the list of sleep queues as well as the " "contents of the sleep queue structures on the list. Only one sleep queue is " "associated with a given wait channel. If multiple threads block on a wait " "channel than the sleep queues associated with all but the first thread are " "stored on a list of free sleep queues in the master sleep queue. When a " "thread is removed from the sleep queue it is given one of the sleep queue " "structures from the master queue's free list if it is not the only thread " "asleep on the queue. The last thread is given the master sleep queue when it " "is resumed. Since threads may be removed from the sleep queue in a different " "order than they are added, a thread may depart from a sleep queue with a " "different sleep queue structure than the one it arrived with." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15702 msgid "" "The sleepq_lock function locks the spin mutex of the " "sleep queue chain that maps to a specific wait channel. The " "sleepq_lookup function looks in the hash table for the " "master sleep queue associated with a given wait channel. If no master sleep " "queue is found, it returns NULL. The " "sleepq_release function unlocks the spin mutex " "associated with a given wait channel." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15711 msgid "" "A thread is added to a sleep queue via the sleepq_add. " "This function accepts the wait channel, a pointer to the mutex that protects " "the wait channel, a wait message description string, and a mask of flags. " "The sleep queue chain should be locked via sleepq_lock " "before this function is called. If no mutex protects the wait channel (or it " "is protected by Giant), then the mutex pointer argument should be " "NULL. The flags argument contains a type field that " "indicates the kind of sleep queue that the thread is being added to and a " "flag to indicate if the sleep is interruptible " "(SLEEPQ_INTERRUPTIBLE). Currently there are only two " "types of sleep queues: traditional sleep queues managed via the " "msleep and wakeup functions " "(SLEEPQ_MSLEEP) and condition variable sleep queues " "(SLEEPQ_CONDVAR). The sleep queue type and lock pointer " "argument are used solely for internal assertion checking. Code that calls " "sleepq_add should explicitly unlock any interlock " "protecting the wait channel after the associated sleepqueue chain has been " "locked via sleepq_lock and before blocking on the sleep " "queue via one of the waiting functions." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15736 msgid "" "A timeout for a sleep is set by invoking sleepq_set_timeout. The function accepts the wait channel and the timeout time as a " "relative tick count as its arguments. If a sleep should be interrupted by " "arriving signals, the sleepq_catch_signals function " "should be called as well. This function accepts the wait channel as its only " "parameter. If there is already a signal pending for this thread, then " "sleepq_catch_signals will return a signal number; " "otherwise, it will return 0." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15747 msgid "" "Once a thread has been added to a sleep queue, it blocks using one of the " "sleepq_wait functions. There are four wait functions " "depending on whether or not the caller wishes to use a timeout or have the " "sleep aborted by caught signals or an interrupt from the userland thread " "scheduler. The sleepq_wait function simply waits until " "the current thread is explicitly resumed by one of the wakeup functions. The " "sleepq_timedwait function waits until either the thread " "is explicitly resumed or the timeout set by an earlier call to " "sleepq_set_timeout expires. The " "sleepq_wait_sig function waits until either the thread " "is explicitly resumed or its sleep is aborted. The " "sleepq_timedwait_sig function waits until either the " "thread is explicitly resumed, the timeout set by an earlier call to " "sleepq_set_timeout expires, or the thread's sleep is " "aborted. All of the wait functions accept the wait channel as their first " "parameter. In addition, the sleepq_timedwait_sig " "function accepts a second boolean parameter to indicate if the earlier call " "to sleepq_catch_signals found a pending signal." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15771 msgid "" "If the thread is explicitly resumed or is aborted by a signal, then a value " "of zero is returned by the wait function to indicate a successful sleep. If " "the thread is resumed by either a timeout or an interrupt from the userland " "thread scheduler then an appropriate errno value is returned instead. Note " "that since sleepq_wait can only return 0 it does not " "return anything and the caller should assume a successful sleep. Also, if a " "thread's sleep times out and is aborted simultaneously then " "sleepq_timedwait_sig will return an error indicating " "that a timeout occurred. If an error value of 0 is returned and either " "sleepq_wait_sig or sleepq_timedwait_sig was used to block, then the function " "sleepq_calc_signal_retval should be called to check for " "any pending signals and calculate an appropriate return value if any are " "found. The signal number returned by the earlier call to " "sleepq_catch_signals should be passed as the sole " "argument to sleepq_calc_signal_retval." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15793 msgid "" "Threads asleep on a wait channel are explicitly resumed by the " "sleepq_broadcast and sleepq_signal " "functions. Both functions accept the wait channel from which to resume " "threads, a priority to raise resumed threads to, and a flags argument to " "indicate which type of sleep queue is being resumed. The priority argument " "is treated as a minimum priority. If a thread being resumed already has a " "higher priority (numerically lower) than the priority argument then its " "priority is not adjusted. The flags argument is used for internal assertions " "to ensure that sleep queues are not being treated as the wrong type. For " "example, the condition variable functions should not resume threads on a " "traditional sleep queue. The sleepq_broadcast function " "resumes all threads that are blocked on the specified wait channel while " "sleepq_signal only resumes the highest priority thread " "blocked on the wait channel. The sleep queue chain should first be locked " "via the sleepq_lock function before calling these " "functions." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15814 msgid "" "A sleeping thread may have its sleep interrupted by calling the " "sleepq_abort function. This function must be called " "with sched_lock held and the thread must be queued on a " "sleep queue. A thread may also be removed from a specific sleep queue via " "the sleepq_remove function. This function accepts both " "a thread and a wait channel as an argument and only awakens the thread if it " "is on the sleep queue for the specified wait channel. If the thread is not " "on a sleep queue or it is on a sleep queue for a different wait channel, " "then this function does nothing." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15828 msgid "Turnstiles" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15830 msgid "turnstiles" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15832 msgid "- Compare/contrast with sleep queues." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15834 msgid "- Lookup/wait/release. - Describe TDF_TSNOBLOCK race." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15837 msgid "- Priority propagation." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15841 msgid "Details of the Mutex Implementation" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15843 msgid "" "- Should we require mutexes to be owned for mtx_destroy() since we can not " "safely assert that they are unowned by anyone else otherwise?" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:15848 msgid "Spin Mutexes" msgstr "" #. (itstool) path: sect3/indexterm #: book.translate.xml:15850 msgid "mutexspin" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15852 msgid "- Use a critical section..." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:15856 msgid "Sleep Mutexes" msgstr "" #. (itstool) path: sect3/indexterm #: book.translate.xml:15858 msgid "mutexsleep" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15859 msgid "- Describe the races with contested mutexes" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:15861 msgid "" "- Why it is safe to read mtx_lock of a contested mutex when holding the " "turnstile chain lock." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15867 msgid "Witness" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:15869 msgid "witness" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15871 msgid "- What does it do" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15873 msgid "- How does it work" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:15878 msgid "Miscellaneous Topics" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15881 msgid "Interrupt Source and ICU Abstractions" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15883 msgid "- struct isrc" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15885 msgid "- pic drivers" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:15889 msgid "Other Random Questions/Topics" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15891 msgid "- Should we pass an interlock into sema_wait?" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15894 msgid "- Should we have non-sleepable sx locks?" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:15896 msgid "- Add some info about proper use of reference counts." msgstr "" #. (itstool) path: glossary/title #: book.translate.xml:15901 msgid "Glossary" msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:15904 msgid "atomic" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15906 msgid "" "An operation is atomic if all of its effects are visible to other CPUs " "together when the proper access protocol is followed. In the degenerate case " "are atomic instructions provided directly by machine architectures. At a " "higher level, if several members of a structure are protected by a lock, " "then a set of operations are atomic if they are all performed while holding " "the lock without releasing the lock in between any of the operations." msgstr "" #. (itstool) path: glossdef/glossseealso #. (itstool) path: glossentry/glossterm #: book.translate.xml:15915 book.translate.xml:15966 msgid "operation" msgstr "" #. (itstool) path: glossentry/glossterm #. (itstool) path: glossdef/glossseealso #: book.translate.xml:15920 book.translate.xml:15998 msgid "block" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15922 msgid "" "A thread is blocked when it is waiting on a lock, resource, or condition. " "Unfortunately this term is a bit overloaded as a result." msgstr "" #. (itstool) path: glossdef/glossseealso #. (itstool) path: glossentry/glossterm #: book.translate.xml:15926 book.translate.xml:15992 book.translate.xml:16011 msgid "sleep" msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:15931 msgid "critical section" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15933 msgid "" "A section of code that is not allowed to be preempted. A critical section is " "entered and exited using the critical_enter9 API." msgstr "" #. (itstool) path: glossentry/glossterm #. (itstool) path: glossdef/glossseealso #: book.translate.xml:15940 book.translate.xml:15961 msgid "MD" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15942 msgid "Machine dependent." msgstr "" #. (itstool) path: glossdef/glossseealso #. (itstool) path: glossentry/glossterm #: book.translate.xml:15944 book.translate.xml:15957 msgid "MI" msgstr "" #. (itstool) path: glossentry/glossterm #. (itstool) path: glossentry/glosssee #: book.translate.xml:15949 book.translate.xml:15967 msgid "memory operation" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15951 msgid "A memory operation reads and/or writes to a memory location." msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15959 msgid "Machine independent." msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:15971 msgid "primary interrupt context" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15973 msgid "" "Primary interrupt context refers to the code that runs when an interrupt " "occurs. This code can either run an interrupt handler directly or schedule " "an asynchronous interrupt thread to execute the interrupt handlers for a " "given interrupt source." msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:15982 msgid "realtime kernel thread" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15984 msgid "" "A high priority kernel thread. Currently, the only realtime priority kernel " "threads are interrupt threads." msgstr "" #. (itstool) path: glossdef/glossseealso #. (itstool) path: glossentry/glossterm #: book.translate.xml:15987 book.translate.xml:16016 msgid "thread" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:15994 msgid "" "A thread is asleep when it is blocked on a condition variable or a sleep " "queue via msleep or tsleep." msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:16003 msgid "sleepable lock" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:16005 msgid "" "A sleepable lock is a lock that can be held by a thread which is asleep. " "Lockmgr locks and sx locks are currently the only sleepable locks in FreeBSD." " Eventually, some sx locks such as the allproc and proctree locks may become " "non-sleepable locks." msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:16018 msgid "" "A kernel thread represented by a struct thread. Threads own locks and hold a " "single execution context." msgstr "" #. (itstool) path: glossentry/glossterm #: book.translate.xml:16024 msgid "wait channel" msgstr "" #. (itstool) path: glossdef/para #: book.translate.xml:16026 msgid "A kernel virtual address that threads may sleep on." msgstr "" #. (itstool) path: part/title #. (itstool) path: sect1/title #: book.translate.xml:16036 book.translate.xml:22448 msgid "Device Drivers" msgstr "" #. (itstool) path: info/title #: book.translate.xml:16048 msgid "Writing FreeBSD Device Drivers" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16051 msgid "" " Murray Stokely Written by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16062 msgid "" " Jörg Wunsch Based on intro(4) manual page by " msgstr "" #. (itstool) path: sect1/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:16076 book.translate.xml:22453 msgid "device driver" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16077 msgid "pseudo-device" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16079 msgid "" "This chapter provides a brief introduction to writing device drivers for " "FreeBSD. A device in this context is a term used mostly for hardware-related " "stuff that belongs to the system, like disks, printers, or a graphics " "display with its keyboard. A device driver is the software component of the " "operating system that controls a specific device. There are also so-called " "pseudo-devices where a device driver emulates the behavior of a device in " "software without any particular underlying hardware. Device drivers can be " "compiled into the system statically or loaded on demand through the dynamic " "kernel linker facility `kld'." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16091 msgid "device nodes" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16093 msgid "" "Most devices in a UNIX-like " "operating system are accessed through device-nodes, sometimes also called " "special files. These files are usually located under the directory " "/dev in the filesystem hierarchy." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16098 msgid "" "Device drivers can roughly be broken down into two categories; character and " "network device drivers." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16104 msgid "Dynamic Kernel Linker Facility - KLD" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16106 msgid "kernel linking dynamic" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16110 msgid "kernel loadable modules (KLD)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16114 msgid "" "The kld interface allows system administrators to dynamically add and remove " "functionality from a running system. This allows device driver writers to " "load their new changes into a running kernel without constantly rebooting to " "test changes." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16120 msgid "kernel modules loading" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16124 msgid "kernel modules unloading" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16128 msgid "kernel modules listing" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16133 msgid "The kld interface is used through:" msgstr "" #. (itstool) path: listitem/simpara #: book.translate.xml:16137 msgid "kldload - loads a new kernel module" msgstr "" #. (itstool) path: listitem/simpara #: book.translate.xml:16140 msgid "kldunload - unloads a kernel module" msgstr "" #. (itstool) path: listitem/simpara #: book.translate.xml:16143 msgid "kldstat - lists loaded modules" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16147 msgid "Skeleton Layout of a kernel module" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16149 #, no-wrap msgid "" "/*\n" " * KLD Skeleton\n" " * Inspired by Andrew Reiter's Daemonnews article\n" " */\n" "\n" "#include <sys/types.h>\n" "#include <sys/module.h>\n" "#include <sys/systm.h> /* uprintf */\n" "#include <sys/errno.h>\n" "#include <sys/param.h> /* defines used in kernel.h */\n" "#include <sys/kernel.h> /* types used in module initialization */\n" "\n" "/*\n" " * Load handler that deals with the loading and unloading of a KLD.\n" " */\n" "\n" "static int\n" "skel_loader(struct module *m, int what, void *arg)\n" "{\n" " int err = 0;\n" "\n" " switch (what) {\n" " case MOD_LOAD: /* kldload */\n" " uprintf(\"Skeleton KLD loaded.\\n\");\n" " break;\n" " case MOD_UNLOAD:\n" " uprintf(\"Skeleton KLD unloaded.\\n\");\n" " break;\n" " default:\n" " err = EOPNOTSUPP;\n" " break;\n" " }\n" " return(err);\n" "}\n" "\n" "/* Declare this module to the rest of the kernel */\n" "\n" "static moduledata_t skel_mod = {\n" " \"skel\",\n" " skel_loader,\n" " NULL\n" "};\n" "\n" "DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:16196 msgid "Makefile" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:16198 msgid "" "FreeBSD provides a system makefile to simplify compiling a kernel module." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:16201 #, no-wrap msgid "SRCS=skeleton.c\n" "KMOD=skeleton\n" "\n" ".include <bsd.kmod.mk>" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:16206 msgid "" "Running make with this makefile will create a file " "skeleton.ko that can be loaded into the kernel by " "typing:" msgstr "" #. (itstool) path: sect2/screen #: book.translate.xml:16210 #, no-wrap msgid "# kldload -v ./skeleton.ko" msgstr "" #. (itstool) path: sect1/title #. (itstool) path: sect2/title #: book.translate.xml:16215 book.translate.xml:22492 msgid "Character Devices" msgstr "" #. (itstool) path: sect1/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:16217 book.translate.xml:22494 msgid "character devices" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16220 msgid "" "A character device driver is one that transfers data directly to and from a " "user process. This is the most common type of device driver and there are " "plenty of simple examples in the source tree." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16225 msgid "" "This simple example pseudo-device remembers whatever values are written to " "it and can then echo them back when read." msgstr "" #. (itstool) path: example/title #: book.translate.xml:16230 msgid "Example of a Sample Echo Pseudo-Device Driver for FreeBSD 10.X - 12.X" msgstr "" #. (itstool) path: example/programlisting #: book.translate.xml:16233 #, no-wrap msgid "" "/*\n" " * Simple Echo pseudo-device KLD\n" " *\n" " * Murray Stokely\n" " * Søren (Xride) Straarup\n" " * Eitan Adler\n" " */\n" "\n" "#include <sys/types.h>\n" "#include <sys/module.h>\n" "#include <sys/systm.h> /* uprintf */\n" "#include <sys/param.h> /* defines used in kernel.h */\n" "#include <sys/kernel.h> /* types used in module initialization */\n" "#include <sys/conf.h> /* cdevsw struct */\n" "#include <sys/uio.h> /* uio struct */\n" "#include <sys/malloc.h>\n" "\n" "#define BUFFERSIZE 255\n" "\n" "/* Function prototypes */\n" "static d_open_t echo_open;\n" "static d_close_t echo_close;\n" "static d_read_t echo_read;\n" "static d_write_t echo_write;\n" "\n" "/* Character device entry points */\n" "static struct cdevsw echo_cdevsw = {\n" " .d_version = D_VERSION,\n" " .d_open = echo_open,\n" " .d_close = echo_close,\n" " .d_read = echo_read,\n" " .d_write = echo_write,\n" " .d_name = \"echo\",\n" "};\n" "\n" "struct s_echo {\n" " char msg[BUFFERSIZE + 1];\n" " int len;\n" "};\n" "\n" "/* vars */\n" "static struct cdev *echo_dev;\n" "static struct s_echo *echomsg;\n" "\n" "MALLOC_DECLARE(M_ECHOBUF);\n" "MALLOC_DEFINE(M_ECHOBUF, \"echobuffer\", \"buffer for echo module\");\n" "\n" "/*\n" " * This function is called by the kld[un]load(2) system calls to\n" " * determine what actions to take when a module is loaded or unloaded.\n" " */\n" "static int\n" "echo_loader(struct module *m __unused, int what, void *arg __unused)\n" "{\n" " int error = 0;\n" "\n" " switch (what) {\n" " case MOD_LOAD: /* kldload */\n" " error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,\n" " &echo_dev,\n" " &echo_cdevsw,\n" " 0,\n" " UID_ROOT,\n" " GID_WHEEL,\n" " 0600,\n" " \"echo\");\n" " if (error != 0)\n" " break;\n" "\n" " echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |\n" " M_ZERO);\n" " printf(\"Echo device loaded.\\n\");\n" " break;\n" " case MOD_UNLOAD:\n" " destroy_dev(echo_dev);\n" " free(echomsg, M_ECHOBUF);\n" " printf(\"Echo device unloaded.\\n\");\n" " break;\n" " default:\n" " error = EOPNOTSUPP;\n" " break;\n" " }\n" " return (error);\n" "}\n" "\n" "static int\n" "echo_open(struct cdev *dev __unused, int oflags __unused, int devtype " "__unused,\n" " struct thread *td __unused)\n" "{\n" " int error = 0;\n" "\n" " uprintf(\"Opened device \\\"echo\\\" successfully.\\n\");\n" " return (error);\n" "}\n" "\n" "static int\n" "echo_close(struct cdev *dev __unused, int fflag __unused, int devtype " "__unused,\n" " struct thread *td __unused)\n" "{\n" "\n" " uprintf(\"Closing device \\\"echo\\\".\\n\");\n" " return (0);\n" "}\n" "\n" "/*\n" " * The read function just takes the buf that was saved via\n" " * echo_write() and returns it to userland for accessing.\n" " * uio(9)\n" " */\n" "static int\n" "echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" "{\n" " size_t amt;\n" " int error;\n" "\n" " /*\n" " * How big is this read operation? Either as big as the user wants,\n" " * or as big as the remaining data. Note that the 'len' does not\n" " * include the trailing null character.\n" " */\n" " amt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? " "0 :\n" " echomsg->len + 1 - uio->uio_offset);\n" "\n" " if ((error = uiomove(echomsg->msg, amt, uio)) != 0)\n" " uprintf(\"uiomove failed!\\n\");\n" "\n" " return (error);\n" "}\n" "\n" "/*\n" " * echo_write takes in a character string and saves it\n" " * to buf for later accessing.\n" " */\n" "static int\n" "echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" "{\n" " size_t amt;\n" " int error;\n" "\n" " /*\n" " * We either write from the beginning or are appending -- do\n" " * not allow random access.\n" " */\n" " if (uio->uio_offset != 0 && (uio->uio_offset != echomsg-" ">len))\n" " return (EINVAL);\n" "\n" " /* This is a new message, reset length */\n" " if (uio->uio_offset == 0)\n" " echomsg->len = 0;\n" "\n" " /* Copy the string in from user memory to kernel memory */\n" " amt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len));\n" "\n" " error = uiomove(echomsg->msg + uio->uio_offset, amt, uio);\n" "\n" " /* Now we need to null terminate and record the length */\n" " echomsg->len = uio->uio_offset;\n" " echomsg->msg[echomsg->len] = 0;\n" "\n" " if (error != 0)\n" " uprintf(\"Write failed: bad address!\\n\");\n" " return (error);\n" "}\n" "\n" "DEV_MODULE(echo, echo_loader, NULL);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16400 msgid "With this driver loaded try:" msgstr "" #. (itstool) path: sect1/screen #: book.translate.xml:16402 #, no-wrap msgid "" "# echo -n \"Test Data\" > /dev/echo\n" "# cat /dev/echo\n" "Opened device \"echo\" successfully.\n" "Test Data\n" "Closing device \"echo\"." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16408 msgid "Real hardware devices are described in the next chapter." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16413 msgid "Block Devices (Are Gone)" msgstr "" #. (itstool) path: sect1/indexterm #. (itstool) path: sect2/indexterm #: book.translate.xml:16415 book.translate.xml:22479 msgid "block devices" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16417 msgid "" "Other UNIX systems may support a " "second type of disk device known as block devices. Block devices are disk " "devices for which the kernel provides caching. This caching makes block-" "devices almost unusable, or at least dangerously unreliable. The caching " "will reorder the sequence of write operations, depriving the application of " "the ability to know the exact disk contents at any one instant in time." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16425 msgid "" "This makes predictable and reliable crash recovery of on-disk data " "structures (filesystems, databases, etc.) impossible. Since writes may be " "delayed, there is no way the kernel can report to the application which " "particular write operation encountered a write error, this further compounds " "the consistency problem." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16432 msgid "" "For this reason, no serious applications rely on block devices, and in fact, " "almost all applications which access disks directly take great pains to " "specify that character (or raw) devices should always be used." " Because the implementation of the aliasing of each disk (partition) to two " "devices with different semantics significantly complicated the relevant " "kernel code FreeBSD dropped support for cached disk devices as part of the " "modernization of the disk I/O infrastructure." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16444 msgid "Network Drivers" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16446 msgid "network devices" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16449 msgid "" "Drivers for network devices do not use device nodes in order to be accessed. " "Their selection is based on other decisions made inside the kernel and " "instead of calling open(), use of a network device is generally introduced " "by using the system call socket(2)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16455 msgid "" "For more information see ifnet(9), the source of the loopback device, and " "Bill Paul's network drivers." msgstr "" #. (itstool) path: info/title #: book.translate.xml:16467 msgid "ISA Device Drivers" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16469 book.translate.xml:19438 msgid "" "SergeyBabkinWritten by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16472 book.translate.xml:19441 msgid "" "MurrayStokelyModifications for Handbook made by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16473 msgid "" "ValentinoVaschetto" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:16474 msgid "" "WylieStilwell" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16483 msgid "ISA" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16484 msgid "device driverISA" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16486 msgid "" "This chapter introduces the issues relevant to writing a driver for an ISA " "device. The pseudo-code presented here is rather detailed and reminiscent of " "the real code but is still only pseudo-code. It avoids the details " "irrelevant to the subject of the discussion. The real-life examples can be " "found in the source code of real drivers. In particular the drivers " "ep and aha are good sources of " "information." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16496 msgid "Basic Information" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16498 msgid "A typical ISA driver would need the following include files:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16501 #, no-wrap msgid "" "#include <sys/module.h>\n" "#include <sys/bus.h>\n" "#include <machine/bus.h>\n" "#include <machine/resource.h>\n" "#include <sys/rman.h>\n" "\n" "#include <isa/isavar.h>\n" "#include <isa/pnpvar.h>" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16510 msgid "" "They describe the things specific to the ISA and generic bus subsystem." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16513 msgid "object-oriented" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16514 msgid "" "The bus subsystem is implemented in an object-oriented fashion, its main " "structures are accessed by associated method functions." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16518 msgid "bus methods" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16519 msgid "" "The list of bus methods implemented by an ISA driver is like one for any " "other bus. For a hypothetical driver named xxx they would be:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16525 msgid "" "static void xxx_isa_identify (driver_t *, device_t); " "Normally used for bus drivers, not device drivers. But for ISA devices this " "method may have special use: if the device provides some device-specific " "(non-PnP) way to auto-detect devices this routine may implement it." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16534 msgid "" "static int xxx_isa_probe (device_t dev); Probe for a " "device at a known (or PnP) location. This routine can also accommodate " "device-specific auto-detection of parameters for partially configured " "devices." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16542 msgid "" "static int xxx_isa_attach (device_t dev); Attach and " "initialize device." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16547 msgid "" "static int xxx_isa_detach (device_t dev); Detach device " "before unloading the driver module." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16553 msgid "" "static int xxx_isa_shutdown (device_t dev); Execute " "shutdown of the device before system shutdown." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16559 msgid "" "static int xxx_isa_suspend (device_t dev); Suspend the " "device before the system goes to the power-save state. May also abort " "transition to the power-save state." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16566 msgid "" "static int xxx_isa_resume (device_t dev); Resume the " "device activity after return from power-save state." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16573 msgid "" "xxx_isa_probe() and xxx_isa_attach() are mandatory, the rest of the routines are optional, depending on " "the device's needs." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16578 msgid "" "The driver is linked to the system with the following set of descriptions." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16581 #, no-wrap msgid "" " /* table of supported bus methods */\n" " static device_method_t xxx_isa_methods[] = {\n" " /* list all the bus method functions supported by the driver */\n" " /* omit the unsupported methods */\n" " DEVMETHOD(device_identify, xxx_isa_identify),\n" " DEVMETHOD(device_probe, xxx_isa_probe),\n" " DEVMETHOD(device_attach, xxx_isa_attach),\n" " DEVMETHOD(device_detach, xxx_isa_detach),\n" " DEVMETHOD(device_shutdown, xxx_isa_shutdown),\n" " DEVMETHOD(device_suspend, xxx_isa_suspend),\n" " DEVMETHOD(device_resume, xxx_isa_resume),\n" "\n" " DEVMETHOD_END\n" " };\n" "\n" " static driver_t xxx_isa_driver = {\n" " \"xxx\",\n" " xxx_isa_methods,\n" " sizeof(struct xxx_softc),\n" " };\n" "\n" "\n" " static devclass_t xxx_devclass;\n" "\n" " DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,\n" " load_function, load_argument);" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16608 msgid "softc" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16610 msgid "" "Here struct xxx_softc is a device-" "specific structure that contains private driver data and descriptors for the " "driver's resources. The bus code automatically allocates one softc " "descriptor per device as needed." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16616 msgid "kernel module" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16618 msgid "" "If the driver is implemented as a loadable module then " "load_function() is called to do driver-specific " "initialization or clean-up when the driver is loaded or unloaded and " "load_argument is passed as one of its arguments. If the driver does not " "support dynamic loading (in other words it must always be linked into the " "kernel) then these values should be set to 0 and the last definition would " "look like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16627 #, no-wrap msgid " DRIVER_MODULE(xxx, isa, xxx_isa_driver,\n" " xxx_devclass, 0, 0);" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16630 msgid "PnP" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16632 msgid "" "If the driver is for a device which supports PnP then a table of supported " "PnP IDs must be defined. The table consists of a list of PnP IDs supported " "by this driver and human-readable descriptions of the hardware types and " "models having these IDs. It looks like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16638 #, no-wrap msgid "" " static struct isa_pnp_id xxx_pnp_ids[] = {\n" " /* a line for each supported PnP ID */\n" " { 0x12345678, \"Our device model 1234A\" },\n" " { 0x12345679, \"Our device model 1234B\" },\n" " { 0, NULL }, /* end of table */\n" " };" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16645 msgid "" "If the driver does not support PnP devices it still needs an empty PnP ID " "table, like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16648 #, no-wrap msgid "" " static struct isa_pnp_id xxx_pnp_ids[] = {\n" " { 0, NULL }, /* end of table */\n" " };" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16655 msgid "device_t Pointer" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16657 msgid "" "device_t is the pointer type for the " "device structure. Here we consider only the methods interesting from the " "device driver writer's standpoint. The methods to manipulate values in the " "device structure are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16665 msgid "" "device_t device_get_parent(dev) Get the parent bus of a " "device." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16669 msgid "" "driver_t device_get_driver(dev) Get pointer to its " "driver structure." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16673 msgid "" "char *device_get_name(dev) Get the driver name, such as " "\"xxx\" for our example." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16677 msgid "" "int device_get_unit(dev) Get the unit number (units are " "numbered from 0 for the devices associated with each driver)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16681 msgid "" "char *device_get_nameunit(dev) Get the device name " "including the unit number, such as xxx0, xxx1 " "and so on." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16686 msgid "" "char *device_get_desc(dev) Get the device description. " "Normally it describes the exact model of device in human-readable form." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16691 msgid "" "device_set_desc(dev, desc) Set the description. This " "makes the device description point to the string desc which may not be " "deallocated or changed after that." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16696 msgid "" "device_set_desc_copy(dev, desc) Set the description. " "The description is copied into an internal dynamically allocated buffer, so " "the string desc may be changed afterwards without adverse effects." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16702 msgid "" "void *device_get_softc(dev) Get pointer to the device " "descriptor (struct xxx_softc) " "associated with this device." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16707 msgid "" "u_int32_t device_get_flags(dev) Get the flags specified " "for the device in the configuration file." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16713 msgid "" "A convenience function device_printf(dev, fmt, ...) may " "be used to print the messages from the device driver. It automatically " "prepends the unitname and colon to the message." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16718 msgid "" "The device_t methods are implemented in the file kern/bus_subr.c." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16724 msgid "" "Configuration File and the Order of Identifying and Probing During Auto-" "Configuration" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16727 msgid "ISAprobing" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16729 msgid "The ISA devices are described in the kernel configuration file like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16732 #, no-wrap msgid "" "device xxx0 at isa? port 0x300 irq 10 drq 5\n" " iomem 0xd0000 flags 0x1 sensitive" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16735 msgid "IRQ" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16737 msgid "" "The values of port, IRQ and so on are converted to the resource values " "associated with the device. They are optional, depending on the device's " "needs and abilities for auto-configuration. For example, some devices do not " "need DRQ at all and some allow the driver to read the IRQ setting from the " "device configuration ports. If a machine has multiple ISA buses the exact " "bus may be specified in the configuration line, like isa0 " "or isa1, otherwise the device would be searched for on " "all the ISA buses." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16747 msgid "" "sensitive is a resource requesting that this device must " "be probed before all non-sensitive devices. It is supported but does not " "seem to be used in any current driver." msgstr "" #. (itstool) path: para/programlisting #: book.translate.xml:16756 #, no-wrap msgid "device xxx0 at isa?" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16751 msgid "" "For legacy ISA devices in many cases the drivers are still able to detect " "the configuration parameters. But each device to be configured in the system " "must have a config line. If two devices of some type are installed in the " "system but there is only one configuration line for the corresponding " "driver, ie: <_:programlisting-1/> then only one device will be configured." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16759 msgid "" "But for the devices supporting automatic identification by the means of Plug-" "n-Play or some proprietary protocol one configuration line is enough to " "configure all the devices in the system, like the one above or just simply:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16764 #, no-wrap msgid "device xxx at isa?" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16766 msgid "" "If a driver supports both auto-identified and legacy devices and both kinds " "are installed at once in one machine then it is enough to describe in the " "config file the legacy devices only. The auto-identified devices will be " "added automatically." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16772 msgid "When an ISA bus is auto-configured the events happen as follows:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16775 msgid "" "All the drivers' identify routines (including the PnP identify routine which " "identifies all the PnP devices) are called in random order. As they identify " "the devices they add them to the list on the ISA bus. Normally the drivers' " "identify routines associate their drivers with the new devices. The PnP " "identify routine does not know about the other drivers yet so it does not " "associate any with the new devices it adds." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16784 msgid "" "The PnP devices are put to sleep using the PnP protocol to prevent them from " "being probed as legacy devices." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16787 msgid "" "The probe routines of non-PnP devices marked as sensitive " "are called. If probe for a device went successfully, the attach routine is " "called for it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16791 msgid "" "The probe and attach routines of all non-PNP devices are called likewise." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16794 msgid "" "The PnP devices are brought back from the sleep state and assigned the " "resources they request: I/O and memory address ranges, IRQs and DRQs, all of " "them not conflicting with the attached legacy devices." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16799 msgid "" "Then for each PnP device the probe routines of all the present ISA drivers " "are called. The first one that claims the device gets attached. It is " "possible that multiple drivers would claim the device with different " "priority; in this case, the highest-priority driver wins. The probe routines " "must call ISA_PNP_PROBE() to compare the actual PnP ID " "with the list of the IDs supported by the driver and if the ID is not in the " "table return failure. That means that absolutely every driver, even the ones " "not supporting any PnP devices must call ISA_PNP_PROBE(), at least with an empty PnP ID table to return failure on unknown " "PnP devices." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16812 msgid "" "The probe routine returns a positive value (the error code) on error, zero " "or negative value on success." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16815 msgid "" "The negative return values are used when a PnP device supports multiple " "interfaces. For example, an older compatibility interface and a newer " "advanced interface which are supported by different drivers. Then both " "drivers would detect the device. The driver which returns a higher value in " "the probe routine takes precedence (in other words, the driver returning 0 " "has highest precedence, returning -1 is next, returning -2 is after it and " "so on). In result the devices which support only the old interface will be " "handled by the old driver (which should return -1 from the probe routine) " "while the devices supporting the new interface as well will be handled by " "the new driver (which should return 0 from the probe routine). If multiple " "drivers return the same value then the one called first wins. So if a driver " "returns value 0 it may be sure that it won the priority arbitration." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16831 msgid "" "The device-specific identify routines can also assign not a driver but a " "class of drivers to the device. Then all the drivers in the class are probed " "for this device, like the case with PnP. This feature is not implemented in " "any existing driver and is not considered further in this document." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16837 msgid "" "Because the PnP devices are disabled when probing the legacy devices they " "will not be attached twice (once as legacy and once as PnP). But in case of " "device-dependent identify routines it is the responsibility of the driver to " "make sure that the same device will not be attached by the driver twice: " "once as legacy user-configured and once as auto-identified." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16845 msgid "" "Another practical consequence for the auto-identified devices (both PnP and " "device-specific) is that the flags can not be passed to them from the kernel " "configuration file. So they must either not use the flags at all or use the " "flags from the device unit 0 for all the auto-identified devices or use the " "sysctl interface instead of flags." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16852 msgid "" "Other unusual configurations may be accommodated by accessing the " "configuration resources directly with functions of families " "resource_query_*() and resource_*_value(). Their implementations are located in kern/subr_bus.c. The old IDE disk driver i386/isa/wd.c " "contains examples of such use. But the standard means of configuration must " "always be preferred. Leave parsing the configuration resources to the bus " "configuration code." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:16865 msgid "Resources" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16867 msgid "resources" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16868 msgid "device driverresources" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16870 msgid "" "The information that a user enters into the kernel configuration file is " "processed and passed to the kernel as configuration resources. This " "information is parsed by the bus configuration code and transformed into a " "value of structure device_t and the bus resources associated with it. The " "drivers may access the configuration resources directly using functions " "resource_* for more complex cases of configuration. " "However, generally this is neither needed nor recommended, so this issue is " "not discussed further here." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16880 msgid "" "The bus resources are associated with each device. They are identified by " "type and number within the type. For the ISA bus the following types are " "defined:" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:16884 msgid "DMA channel" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16888 msgid "SYS_RES_IRQ - interrupt number" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16893 msgid "SYS_RES_DRQ - ISA DMA channel number" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16898 msgid "" "SYS_RES_MEMORY - range of device memory mapped into the " "system memory space" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16904 msgid "SYS_RES_IOPORT - range of device I/O registers" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16909 msgid "" "The enumeration within types starts from 0, so if a device has two memory " "regions it would have resources of type SYS_RES_MEMORY " "numbered 0 and 1. The resource type has nothing to do with the C language " "type, all the resource values have the C language type unsigned " "long and must be cast as necessary. The resource numbers do not " "have to be contiguous, although for ISA they normally would be. The " "permitted resource numbers for ISA devices are:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:16918 #, no-wrap msgid "" " IRQ: 0-1\n" " DRQ: 0-1\n" " MEMORY: 0-3\n" " IOPORT: 0-7" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16923 msgid "" "All the resources are represented as ranges, with a start value and count. " "For IRQ and DRQ resources the count would normally be equal to 1. The values " "for memory refer to the physical addresses." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16928 msgid "Three types of activities can be performed on resources:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16932 msgid "set/get" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16933 msgid "allocate/release" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16934 msgid "activate/deactivate" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16937 msgid "" "Setting sets the range used by the resource. Allocation reserves the " "requested range that no other driver would be able to reserve it (and " "checking that no other driver reserved this range already). Activation makes " "the resource accessible to the driver by doing whatever is necessary for " "that (for example, for memory it would be mapping into the kernel virtual " "address space)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:16945 msgid "The functions to manipulate resources are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16949 msgid "" "int bus_set_resource(device_t dev, int type, int rid, u_long " "start, u_long count)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16952 msgid "" "Set a range for a resource. Returns 0 if successful, error code otherwise. " "Normally, this function will return an error only if one of type, rid, start or " "count has a value that falls out of the permitted range." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16961 msgid "dev - driver's device" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16964 msgid "type - type of resource, SYS_RES_*" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16967 msgid "rid - resource number (ID) within type" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16970 msgid "start, count - resource range" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16976 msgid "" "int bus_get_resource(device_t dev, int type, int rid, u_long " "*startp, u_long *countp)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16979 msgid "" "Get the range of resource. Returns 0 if successful, error code if the " "resource is not defined yet." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16984 msgid "" "u_long bus_get_resource_start(device_t dev, int type, int rid) " "u_long bus_get_resource_count (device_t dev, int type, int rid)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16988 msgid "" "Convenience functions to get only the start or count. Return 0 in case of " "error, so if the resource start has 0 among the legitimate values it would " "be impossible to tell if the value is 0 or an error occurred. Luckily, no " "ISA resources for add-on drivers may have a start value equal to 0." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16997 msgid "" "void bus_delete_resource(device_t dev, int type, int rid)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:16999 msgid "Delete a resource, make it undefined." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17003 msgid "" "struct resource * bus_alloc_resource(device_t dev, int type, int " "*rid, u_long start, u_long end, u_long count, u_int flags)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17008 msgid "" "Allocate a resource as a range of count values not allocated by anyone else, " "somewhere between start and end. Alas, alignment is not supported. If the " "resource was not set yet it is automatically created. The special values of " "start 0 and end ~0 (all ones) means that the fixed values previously set by " "bus_set_resource() must be used instead: start and " "count as themselves and end=(start+count), in this case if the resource was " "not defined before then an error is returned. Although rid is passed by " "reference it is not set anywhere by the resource allocation code of the ISA " "bus. (The other buses may use a different approach and modify it)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17024 msgid "Flags are a bitmap, the flags interesting for the caller are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17029 msgid "" "RF_ACTIVE - causes the resource to be automatically " "activated after allocation." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17034 msgid "" "RF_SHAREABLE - resource may be shared at the same time " "by multiple drivers." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17039 msgid "" "RF_TIMESHARE - resource may be time-shared by multiple " "drivers, i.e., allocated at the same time by many but activated only by one " "at any given moment of time." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17046 msgid "" "Returns 0 on error. The allocated values may be obtained from the returned " "handle using methods rhand_*()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17051 msgid "" "int bus_release_resource(device_t dev, int type, int rid, struct " "resource *r)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17056 msgid "" "Release the resource, r is the handle returned by " "bus_alloc_resource(). Returns 0 on success, error code " "otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17062 msgid "" "int bus_activate_resource(device_t dev, int type, int rid, struct " "resource *r) int bus_deactivate_resource(device_t dev, " "int type, int rid, struct resource *r)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17069 msgid "" "Activate or deactivate resource. Return 0 on success, error code otherwise. " "If the resource is time-shared and currently activated by another driver " "then EBUSY is returned." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17076 msgid "" "int bus_setup_intr(device_t dev, struct resource *r, int flags, " "driver_intr_t *handler, void *arg, void **cookiep) int " "bus_teardown_intr(device_t dev, struct resource *r, void *cookie)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17084 msgid "" "Associate or de-associate the interrupt handler with a device. Return 0 on " "success, error code otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17089 msgid "r - the activated resource handler describing the IRQ" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17091 msgid "flags - the interrupt priority level, one of:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17095 msgid "" "INTR_TYPE_TTY - terminals and other likewise character-" "type devices. To mask them use spltty()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17100 msgid "" "(INTR_TYPE_TTY | INTR_TYPE_FAST) - terminal type " "devices with small input buffer, critical to the data loss on input (such as " "the old-fashioned serial ports). To mask them use spltty()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17107 msgid "" "INTR_TYPE_BIO - block-type devices, except those on the " "CAM controllers. To mask them use splbio()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17112 msgid "" "INTR_TYPE_CAM - CAM (Common Access Method) bus " "controllers. To mask them use splcam()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17117 msgid "" "INTR_TYPE_NET - network interface controllers. To mask " "them use splimp()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17122 msgid "" "INTR_TYPE_MISC - miscellaneous devices. There is no " "other way to mask them than by splhigh() which masks " "all interrupts." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17131 msgid "" "When an interrupt handler executes all the other interrupts matching its " "priority level will be masked. The only exception is the MISC level for " "which no other interrupts are masked and which is not masked by any other " "interrupt." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17139 msgid "" "handler - pointer to the handler function, the type " "driver_intr_t is defined as void driver_intr_t(void *)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17144 msgid "" "arg - the argument passed to the handler to identify " "this particular device. It is cast from void* to any real type by the " "handler. The old convention for the ISA interrupt handlers was to use the " "unit number as argument, the new (recommended) convention is using a pointer " "to the device softc structure." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17152 msgid "" "cookie[p] - the value received from setup() is used to identify the handler when passed to " "teardown()" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17159 msgid "" "A number of methods are defined to operate on the resource handlers (struct " "resource *). Those of interest to the device driver writers are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17165 msgid "" "u_long rman_get_start(r) u_long rman_get_end(r) Get the " "start and end of allocated resource range." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17170 msgid "" "void *rman_get_virtual(r) Get the virtual address of " "activated memory resource." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:17178 msgid "Bus Memory Mapping" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17180 msgid "" "In many cases data is exchanged between the driver and the device through " "the memory. Two variants are possible:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17183 msgid "(a) memory is located on the device card" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17184 msgid "(b) memory is the main memory of the computer" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17186 msgid "" "In case (a) the driver always copies the data back and forth between the on-" "card memory and the main memory as necessary. To map the on-card memory into " "the kernel virtual address space the physical address and length of the on-" "card memory must be defined as a SYS_RES_MEMORY resource. " "That resource can then be allocated and activated, and its virtual address " "obtained using rman_get_virtual(). The older drivers " "used the function pmap_mapdev() for this purpose, which " "should not be used directly any more. Now it is one of the internal steps of " "resource activation." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17198 msgid "" "Most of the ISA cards will have their memory configured for physical " "location somewhere in range 640KB-1MB. Some of the ISA cards require larger " "memory ranges which should be placed somewhere under 16MB (because of the 24-" "bit address limitation on the ISA bus). In that case if the machine has more " "memory than the start address of the device memory (in other words, they " "overlap) a memory hole must be configured at the address range used by " "devices. Many BIOSes allow configuration of a memory hole of 1MB starting at " "14MB or 15MB. FreeBSD can handle the memory holes properly if the BIOS " "reports them properly (this feature may be broken on old BIOSes)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17210 msgid "" "In case (b) just the address of the data is sent to the device, and the " "device uses DMA to actually access the data in the main memory. Two " "limitations are present: First, ISA cards can only access memory below 16MB. " "Second, the contiguous pages in virtual address space may not be contiguous " "in physical address space, so the device may have to do scatter/gather " "operations. The bus subsystem provides ready solutions for some of these " "problems, the rest has to be done by the drivers themselves." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17220 msgid "" "Two structures are used for DMA memory allocation, bus_dma_tag_t and bus_dmamap_t. Tag describes the properties " "required for the DMA memory. Map represents a memory block allocated " "according to these properties. Multiple maps may be associated with the same " "tag." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17226 msgid "" "Tags are organized into a tree-like hierarchy with inheritance of the " "properties. A child tag inherits all the requirements of its parent tag, and " "may make them more strict but never more loose." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17231 msgid "" "Normally one top-level tag (with no parent) is created for each device unit. " "If multiple memory areas with different requirements are needed for each " "device then a tag for each of them may be created as a child of the parent " "tag." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17236 msgid "The tags can be used to create a map in two ways." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17238 msgid "" "First, a chunk of contiguous memory conformant with the tag requirements may " "be allocated (and later may be freed). This is normally used to allocate " "relatively long-living areas of memory for communication with the device. " "Loading of such memory into a map is trivial: it is always considered as one " "chunk in the appropriate physical memory range." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17246 msgid "" "Second, an arbitrary area of virtual memory may be loaded into a map. Each " "page of this memory will be checked for conformance to the map requirement. " "If it conforms then it is left at its original location. If it is not then a " "fresh conformant bounce page is allocated and used as " "intermediate storage. When writing the data from the non-conformant original " "pages they will be copied to their bounce pages first and then transferred " "from the bounce pages to the device. When reading the data would go from the " "device to the bounce pages and then copied to their non-conformant original " "pages. The process of copying between the original and bounce pages is " "called synchronization. This is normally used on a per-transfer basis: " "buffer for each transfer would be loaded, transfer done and buffer unloaded." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17261 msgid "The functions working on the DMA memory are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17265 msgid "" "int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, " "bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, " "bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int " "nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17271 msgid "Create a new tag. Returns 0 on success, the error code otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17276 msgid "" "parent - parent tag, or NULL to create a top-level tag." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17281 msgid "" "alignment - required physical alignment of the memory " "area to be allocated for this tag. Use value 1 for no specific " "alignment. Applies only to the future bus_dmamem_alloc() but not bus_dmamap_create() calls." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17290 msgid "" "boundary - physical address boundary that must not be " "crossed when allocating the memory. Use value 0 for no boundary. Applies only to the future bus_dmamem_alloc() " "but not bus_dmamap_create() calls. Must be power of 2. " "If the memory is planned to be used in non-cascaded DMA mode (i.e., the DMA " "addresses will be supplied not by the device itself but by the ISA DMA " "controller) then the boundary must be no larger than 64KB (64*1024) due to " "the limitations of the DMA hardware." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17304 msgid "" "lowaddr, highaddr - the names are slightly misleading; " "these values are used to limit the permitted range of physical addresses " "used to allocate the memory. The exact meaning varies depending on the " "planned future use:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17312 msgid "" "For bus_dmamem_alloc() all the addresses from 0 to " "lowaddr-1 are considered permitted, the higher ones are forbidden." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17318 msgid "" "For bus_dmamap_create() all the addresses outside the " "inclusive range [lowaddr; highaddr] are considered accessible. The addresses " "of pages inside the range are passed to the filter function which decides if " "they are accessible. If no filter function is supplied then all the range is " "considered unaccessible." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17328 msgid "For the ISA devices the normal values (with no filter function) are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17330 msgid "lowaddr = BUS_SPACE_MAXADDR_24BIT" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17331 msgid "highaddr = BUS_SPACE_MAXADDR" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17338 msgid "" "filter, filterarg - the filter function and its " "argument. If NULL is passed for filter then the whole range [lowaddr, " "highaddr] is considered unaccessible when doing " "bus_dmamap_create(). Otherwise the physical address of " "each attempted page in range [lowaddr; highaddr] is passed to the filter " "function which decides if it is accessible. The prototype of the filter " "function is: int filterfunc(void *arg, bus_addr_t paddr). It must return 0 if the page is accessible, non-zero otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17352 msgid "" "maxsize - the maximal size of memory (in bytes) that " "may be allocated through this tag. In case it is difficult to estimate or " "could be arbitrarily big, the value for ISA devices would be " "BUS_SPACE_MAXSIZE_24BIT." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17360 msgid "" "nsegments - maximal number of scatter-gather segments " "supported by the device. If unrestricted then the value " "BUS_SPACE_UNRESTRICTED should be used. This value is " "recommended for the parent tags, the actual restrictions would then be " "specified for the descendant tags. Tags with nsegments equal to " "BUS_SPACE_UNRESTRICTED may not be used to actually load " "maps, they may be used only as parent tags. The practical limit for " "nsegments seems to be about 250-300, higher values will cause kernel stack " "overflow (the hardware can not normally support that many scatter-gather " "buffers anyway)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17375 msgid "" "maxsegsz - maximal size of a scatter-gather segment " "supported by the device. The maximal value for ISA device would be " "BUS_SPACE_MAXSIZE_24BIT." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17382 msgid "" "flags - a bitmap of flags. The only interesting flags " "are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17387 msgid "" "BUS_DMA_ALLOCNOW - requests to allocate all the " "potentially needed bounce pages when creating the tag." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17393 msgid "" "BUS_DMA_ISA - mysterious flag used only on Alpha " "machines. It is not defined for the i386 machines. Probably it should be " "used by all the ISA drivers for Alpha machines but it looks like there are " "no such drivers yet." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17403 msgid "" "dmat - pointer to the storage for the new tag to be " "returned." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17412 msgid "int bus_dma_tag_destroy(bus_dma_tag_t dmat)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17415 msgid "Destroy a tag. Returns 0 on success, the error code otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17418 msgid "dmat - the tag to be destroyed." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17423 msgid "" "int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, " "bus_dmamap_t *mapp)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17427 msgid "" "Allocate an area of contiguous memory described by the tag. The size of " "memory to be allocated is tag's maxsize. Returns 0 on success, the error " "code otherwise. The result still has to be loaded by " "bus_dmamap_load() before being used to get the physical " "address of the memory." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17436 book.translate.xml:17492 book.translate.xml:17523 #: book.translate.xml:17595 msgid "dmat - the tag" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17441 msgid "" "vaddr - pointer to the storage for the kernel virtual " "address of the allocated area to be returned." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17448 msgid "flags - a bitmap of flags. The only interesting flag is:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17453 msgid "" "BUS_DMA_NOWAIT - if the memory is not immediately " "available return the error. If this flag is not set then the routine is " "allowed to sleep until the memory becomes available." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17464 msgid "" "mapp - pointer to the storage for the new map to be " "returned." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17473 msgid "" "void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t " "map)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17477 msgid "" "Free the memory allocated by bus_dmamem_alloc(). At " "present, freeing of the memory allocated with ISA restrictions is not " "implemented. Because of this the recommended model of use is to keep and re-" "use the allocated areas for as long as possible. Do not lightly free some " "area and then shortly allocate it again. That does not mean that " "bus_dmamem_free() should not be used at all: hopefully " "it will be properly implemented soon." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17496 msgid "vaddr - the kernel virtual address of the memory" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17502 msgid "" "map - the map of the memory (as returned from " "bus_dmamem_alloc())" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17512 msgid "" "int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t " "*mapp)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17516 msgid "" "Create a map for the tag, to be used in bus_dmamap_load() later. Returns 0 on success, the error code otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17528 msgid "" "flags - theoretically, a bit map of flags. But no flags " "are defined yet, so at present it will be always 0." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17535 msgid "" "mapp - pointer to the storage for the new map to be " "returned" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17544 msgid "" "int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17548 msgid "Destroy a map. Returns 0 on success, the error code otherwise." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17554 msgid "dmat - the tag to which the map is associated" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17559 msgid "map - the map to be destroyed" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17567 msgid "" "int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void " "*buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void " "*callback_arg, int flags)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17573 msgid "" "Load a buffer into the map (the map must be previously created by " "bus_dmamap_create() or bus_dmamem_alloc()). All the pages of the buffer are checked for conformance to the " "tag requirements and for those not conformant the bounce pages are allocated." " An array of physical segment descriptors is built and passed to the " "callback routine. This callback routine is then expected to handle it in " "some way. The number of bounce buffers in the system is limited, so if the " "bounce buffers are needed but not immediately available the request will be " "queued and the callback will be called when the bounce buffers will become " "available. Returns 0 if the callback was executed immediately or " "EINPROGRESS if the request was queued for future " "execution. In the latter case the synchronization with queued callback " "routine is the responsibility of the driver." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17600 msgid "map - the map" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17605 msgid "buf - kernel virtual address of the buffer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17611 msgid "buflen - length of the buffer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17616 msgid "" "callback, callback_arg - the " "callback function and its argument" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17624 msgid "The prototype of callback function is:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17627 msgid "" "void callback(void *arg, bus_dma_segment_t *seg, int nseg, int " "error)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17634 msgid "" "arg - the same as callback_arg passed to " "bus_dmamap_load()" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17640 msgid "seg - array of the segment descriptors" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17646 msgid "nseg - number of descriptors in array" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17652 msgid "" "error - indication of the segment number overflow: if " "it is set to EFBIG then the buffer did not fit into " "the maximal number of segments permitted by the tag. In this case only the " "permitted number of descriptors will be in the array. Handling of this " "situation is up to the driver: depending on the desired semantics it can " "either consider this an error or split the buffer in two and handle the " "second part separately" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17666 msgid "Each entry in the segments array contains the fields:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17673 msgid "ds_addr - physical bus address of the segment" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17679 msgid "ds_len - length of the segment" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17688 msgid "" "void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17692 msgid "unload the map." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17697 book.translate.xml:17726 msgid "dmat - tag" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17702 book.translate.xml:17731 msgid "map - loaded map" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17711 msgid "" "void bus_dmamap_sync (bus_dma_tag_t dmat, bus_dmamap_t map, " "bus_dmasync_op_t op)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17715 msgid "" "Synchronise a loaded buffer with its bounce pages before and after physical " "transfer to or from device. This is the function that does all the necessary " "copying of data between the original buffer and its mapped version. The " "buffers must be synchronized both before and after doing the transfer." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17736 msgid "" "op - type of synchronization operation to perform:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17745 msgid "" "BUS_DMASYNC_PREREAD - before reading from device into " "buffer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17751 msgid "" "BUS_DMASYNC_POSTREAD - after reading from device into " "buffer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17757 msgid "" "BUS_DMASYNC_PREWRITE - before writing the buffer to " "device" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:17763 msgid "" "BUS_DMASYNC_POSTWRITE - after writing the buffer to " "device" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17774 msgid "" "As of now PREREAD and POSTWRITE are null operations but that may change in " "the future, so they must not be ignored in the driver. Synchronization is " "not needed for the memory obtained from bus_dmamem_alloc()." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17780 msgid "" "Before calling the callback function from bus_dmamap_load() the segment array is stored in the stack. And it gets pre-" "allocated for the maximal number of segments allowed by the tag. Because of " "this the practical limit for the number of segments on i386 architecture is " "about 250-300 (the kernel stack is 4KB minus the size of the user structure, " "size of a segment array entry is 8 bytes, and some space must be left). " "Because the array is allocated based on the maximal number this value must " "not be set higher than really needed. Fortunately, for most of hardware the " "maximal supported number of segments is much lower. But if the driver wants " "to handle buffers with a very large number of scatter-gather segments it " "should do that in portions: load part of the buffer, transfer it to the " "device, load next part of the buffer, and so on." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17797 msgid "" "Another practical consequence is that the number of segments may limit the " "size of the buffer. If all the pages in the buffer happen to be physically " "non-contiguous then the maximal supported buffer size for that fragmented " "case would be (nsegments * page_size). For example, if a maximal number of " "10 segments is supported then on i386 maximal guaranteed supported buffer " "size would be 40K. If a higher size is desired then special tricks should be " "used in the driver." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17807 msgid "" "If the hardware does not support scatter-gather at all or the driver wants " "to support some buffer size even if it is heavily fragmented then the " "solution is to allocate a contiguous buffer in the driver and use it as " "intermediate storage if the original buffer does not fit." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17814 msgid "" "Below are the typical call sequences when using a map depend on the use of " "the map. The characters -> are used to show the flow of time." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17819 msgid "" "For a buffer which stays practically fixed during all the time between " "attachment and detachment of a device:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17822 msgid "" "bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... -> -> " "bus_dmamap_unload -> bus_dmamem_free" msgstr "" #. (itstool) path: para/programlisting #: book.translate.xml:17831 #, no-wrap msgid "" " bus_dmamap_create ->\n" " -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do " "transfer ->\n" " -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->\n" " ...\n" " -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do " "transfer ->\n" " -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->\n" " -> bus_dmamap_destroy " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17827 msgid "" "For a buffer that changes frequently and is passed from outside the driver: " "<_:programlisting-1/>" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17840 msgid "" "When loading a map created by bus_dmamem_alloc() the " "passed address and size of the buffer must be the same as used in " "bus_dmamem_alloc(). In this case it is guaranteed that " "the whole buffer will be mapped as one segment (so the callback may be based " "on this assumption) and the request will be executed immediately " "(EINPROGRESS will never be returned). All the callback needs to do in this " "case is to save the physical address." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17851 msgid "A typical example would be:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:17855 #, no-wrap msgid "" " static void\n" " alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int " "error)\n" " {\n" " *(bus_addr_t *)arg = seg[0].ds_addr;\n" " }\n" "\n" " ...\n" " int error;\n" " struct somedata {\n" " ....\n" " };\n" " struct somedata *vsomedata; /* virtual address */\n" " bus_addr_t psomedata; /* physical bus-relative address */\n" " bus_dma_tag_t tag_somedata;\n" " bus_dmamap_t map_somedata;\n" " ...\n" "\n" " error=bus_dma_tag_create(parent_tag, alignment,\n" " boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,\n" " /*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,\n" " /*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,\n" " &tag_somedata);\n" " if(error)\n" " return error;\n" "\n" " error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ " "0,\n" " &map_somedata);\n" " if(error)\n" " return error;\n" "\n" " bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,\n" " sizeof (struct somedata), alloc_callback,\n" " (void *) &psomedata, /*flags*/0); " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17889 msgid "" "Looks a bit long and complicated but that is the way to do it. The practical " "consequence is: if multiple memory areas are allocated always together it " "would be a really good idea to combine them all into one structure and " "allocate as one (if the alignment and boundary limitations permit)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17896 msgid "" "When loading an arbitrary buffer into the map created by " "bus_dmamap_create() special measures must be taken to " "synchronize with the callback in case it would be delayed. The code would " "look like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:17903 #, no-wrap msgid "" " {\n" " int s;\n" " int error;\n" "\n" " s = splsoftvm();\n" " error = bus_dmamap_load(\n" " dmat,\n" " dmamap,\n" " buffer_ptr,\n" " buffer_len,\n" " callback,\n" " /*callback_arg*/ buffer_descriptor,\n" " /*flags*/0);\n" " if (error == EINPROGRESS) {\n" " /*\n" " * Do whatever is needed to ensure synchronization\n" " * with callback. Callback is guaranteed not to be started\n" " * until we do splx() or tsleep().\n" " */\n" " }\n" " splx(s);\n" " } " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17926 msgid "Two possible approaches for the processing of requests are:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17929 msgid "" "1. If requests are completed by marking them explicitly as done (such as the " "CAM requests) then it would be simpler to put all the further processing " "into the callback driver which would mark the request when it is done. Then " "not much extra synchronization is needed. For the flow control reasons it " "may be a good idea to freeze the request queue until this request gets " "completed." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17938 msgid "" "2. If requests are completed when the function returns (such as classic read " "or write requests on character devices) then a synchronization flag should " "be set in the buffer descriptor and tsleep() called. " "Later when the callback gets called it will do its processing and check this " "synchronization flag. If it is set then the callback should issue a wakeup. " "In this approach the callback function could either do all the needed " "processing (just like the previous case) or simply save the segments array " "in the buffer descriptor. Then after callback completes the calling function " "could use this saved segments array and do all the processing." msgstr "" #. (itstool) path: sect1/title #. (itstool) path: sect2/title #: book.translate.xml:17958 book.translate.xml:19379 msgid "DMA" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:17961 msgid "Direct Memory Access (DMA)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17963 msgid "" "The Direct Memory Access (DMA) is implemented in the ISA bus through the DMA " "controller (actually, two of them but that is an irrelevant detail). To make " "the early ISA devices simple and cheap the logic of the bus control and " "address generation was concentrated in the DMA controller. Fortunately, " "FreeBSD provides a set of functions that mostly hide the annoying details of " "the DMA controller from the device drivers." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17974 msgid "" "The simplest case is for the fairly intelligent devices. Like the bus master " "devices on PCI they can generate the bus cycles and memory addresses all by " "themselves. The only thing they really need from the DMA controller is bus " "arbitration. So for this purpose they pretend to be cascaded slave DMA " "controllers. And the only thing needed from the system DMA controller is to " "enable the cascaded mode on a DMA channel by calling the following function " "when attaching the driver:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17986 msgid "void isa_dmacascade(int channel_number)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17990 msgid "" "All the further activity is done by programming the device. When detaching " "the driver no DMA-related functions need to be called." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:17996 msgid "" "For the simpler devices things get more complicated. The functions used are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18004 msgid "int isa_dma_acquire(int chanel_number)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18007 msgid "" "Reserve a DMA channel. Returns 0 on success or EBUSY if the channel was " "already reserved by this or a different driver. Most of the ISA devices are " "not able to share DMA channels anyway, so normally this function is called " "when attaching a device. This reservation was made redundant by the modern " "interface of bus resources but still must be used in addition to the latter. " "If not used then later, other DMA routines will panic." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18021 msgid "int isa_dma_release(int chanel_number)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18024 msgid "" "Release a previously reserved DMA channel. No transfers must be in progress " "when the channel is released (in addition the device must not try to " "initiate transfer after the channel is released)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18033 msgid "void isa_dmainit(int chan, u_int bouncebufsize)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18037 msgid "" "Allocate a bounce buffer for use with the specified channel. The requested " "size of the buffer can not exceed 64KB. This bounce buffer will be " "automatically used later if a transfer buffer happens to be not physically " "contiguous or outside of the memory accessible by the ISA bus or crossing " "the 64KB boundary. If the transfers will be always done from buffers which " "conform to these conditions (such as those allocated by " "bus_dmamem_alloc() with proper limitations) then " "isa_dmainit() does not have to be called. But it is " "quite convenient to transfer arbitrary data using the DMA controller. The " "bounce buffer will automatically care of the scatter-gather issues." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18057 msgid "chan - channel number" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18062 msgid "" "bouncebufsize - size of the bounce buffer in bytes" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18073 msgid "" "void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int " "chan)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18077 msgid "" "Prepare to start a DMA transfer. This function must be called to set up the " "DMA controller before actually starting transfer on the device. It checks " "that the buffer is contiguous and falls into the ISA memory range, if not " "then the bounce buffer is automatically used. If bounce buffer is required " "but not set up by isa_dmainit() or too small for the " "requested transfer size then the system will panic. In case of a write " "request with bounce buffer the data will be automatically copied to the " "bounce buffer." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18092 msgid "" "flags - a bitmask determining the type of operation to be done. The " "direction bits B_READ and B_WRITE are mutually exclusive." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18099 msgid "B_READ - read from the ISA bus into memory" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18104 msgid "B_WRITE - write from the memory to the ISA bus" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18109 msgid "" "B_RAW - if set then the DMA controller will remember the buffer and after " "the end of transfer will automatically re-initialize itself to repeat " "transfer of the same buffer again (of course, the driver may change the data " "in the buffer before initiating another transfer in the device). If not set " "then the parameters will work only for one transfer, and " "isa_dmastart() will have to be called again before " "initiating the next transfer. Using B_RAW makes sense only if the bounce " "buffer is not used." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18127 msgid "addr - virtual address of the buffer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18132 msgid "" "nbytes - length of the buffer. Must be less or equal to 64KB. Length of 0 is " "not allowed: the DMA controller will understand it as 64KB while the kernel " "code will understand it as 0 and that would cause unpredictable effects. For " "channels number 4 and higher the length must be even because these channels " "transfer 2 bytes at a time. In case of an odd length the last byte will not " "be transferred." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18144 msgid "chan - channel number" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18150 msgid "" "void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18154 msgid "" "Synchronize the memory after device reports that transfer is done. If that " "was a read operation with a bounce buffer then the data will be copied from " "the bounce buffer to the original buffer. Arguments are the same as for " "isa_dmastart(). Flag B_RAW is permitted but it does not " "affect isa_dmadone() in any way." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18166 msgid "int isa_dmastatus(int channel_number)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18169 msgid "" "Returns the number of bytes left in the current transfer to be transferred. " "In case the flag B_READ was set in isa_dmastart() the " "number returned will never be equal to zero. At the end of transfer it will " "be automatically reset back to the length of buffer. The normal use is to " "check the number of bytes left after the device signals that the transfer is " "completed. If the number of bytes is not 0 then something probably went " "wrong with that transfer." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18183 msgid "int isa_dmastop(int channel_number)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:18186 msgid "" "Aborts the current transfer and returns the number of bytes left " "untransferred." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18195 msgid "xxx_isa_probe" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18198 msgid "" "This function probes if a device is present. If the driver supports auto-" "detection of some part of device configuration (such as interrupt vector or " "memory address) this auto-detection must be done in this routine." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18205 msgid "" "As for any other bus, if the device cannot be detected or is detected but " "failed the self-test or some other problem happened then it returns a " "positive value of error. The value ENXIO must be " "returned if the device is not present. Other error values may mean other " "conditions. Zero or negative values mean success. Most of the drivers return " "zero as success." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18215 msgid "" "The negative return values are used when a PnP device supports multiple " "interfaces. For example, an older compatibility interface and a newer " "advanced interface which are supported by different drivers. Then both " "drivers would detect the device. The driver which returns a higher value in " "the probe routine takes precedence (in other words, the driver returning 0 " "has highest precedence, one returning -1 is next, one returning -2 is after " "it and so on). In result the devices which support only the old interface " "will be handled by the old driver (which should return -1 from the probe " "routine) while the devices supporting the new interface as well will be " "handled by the new driver (which should return 0 from the probe routine)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18231 msgid "" "The device descriptor struct xxx_softc is allocated by the system before " "calling the probe routine. If the probe routine returns an error the " "descriptor will be automatically deallocated by the system. So if a probing " "error occurs the driver must make sure that all the resources it used during " "probe are deallocated and that nothing keeps the descriptor from being " "safely deallocated. If the probe completes successfully the descriptor will " "be preserved by the system and later passed to the routine " "xxx_isa_attach(). If a driver returns a negative value " "it can not be sure that it will have the highest priority and its attach " "routine will be called. So in this case it also must release all the " "resources before returning and if necessary allocate them again in the " "attach routine. When xxx_isa_probe() returns 0 " "releasing the resources before returning is also a good idea and a well-" "behaved driver should do so. But in cases where there is some problem with " "releasing the resources the driver is allowed to keep resources between " "returning 0 from the probe routine and execution of the attach routine." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18255 msgid "" "A typical probe routine starts with getting the device descriptor and unit:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18260 #, no-wrap msgid "" " struct xxx_softc *sc = device_get_softc(dev);\n" " int unit = device_get_unit(dev);\n" " int pnperror;\n" " int error = 0;\n" "\n" " sc->dev = dev; /* link it back */\n" " sc->unit = unit; " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18268 msgid "" "Then check for the PnP devices. The check is carried out by a table " "containing the list of PnP IDs supported by this driver and human-readable " "descriptions of the device models corresponding to these IDs." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18275 #, no-wrap msgid "" "\n" " pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,\n" " xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18280 msgid "" "The logic of ISA_PNP_PROBE is the following: If this card (device unit) was " "not detected as PnP then ENOENT will be returned. If it was detected as PnP " "but its detected ID does not match any of the IDs in the table then ENXIO is " "returned. Finally, if it has PnP support and it matches on of the IDs in the " "table, 0 is returned and the appropriate description from the table is set " "by device_set_desc()." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18291 msgid "" "If a driver supports only PnP devices then the condition would look like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18296 #, no-wrap msgid " if(pnperror != 0)\n" " return pnperror; " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18299 msgid "" "No special treatment is required for the drivers which do not support PnP " "because they pass an empty PnP ID table and will always get ENXIO if called " "on a PnP card." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18305 msgid "" "The probe routine normally needs at least some minimal set of resources, " "such as I/O port number to find the card and probe it. Depending on the " "hardware the driver may be able to discover the other necessary resources " "automatically. The PnP devices have all the resources pre-set by the PnP " "subsystem, so the driver does not need to discover them by itself." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18315 msgid "" "Typically the minimal information required to get access to the device is " "the I/O port number. Then some devices allow to get the rest of information " "from the device configuration registers (though not all devices do that). So " "first we try to get the port start value:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18323 #, no-wrap msgid "" " sc->port0 = bus_get_resource_start(dev,\n" " SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18327 msgid "" "The base port address is saved in the structure softc for future use. If it " "will be used very often then calling the resource function each time would " "be prohibitively slow. If we do not get a port we just return an error. Some " "device drivers can instead be clever and try to probe all the possible " "ports, like this:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18336 #, no-wrap msgid "" "\n" " /* table of all possible base I/O port addresses for this device */" "\n" " static struct xxx_allports {\n" " u_short port; /* port address */\n" " short used; /* flag: if this port is already used by some unit " "*/\n" " } xxx_allports = {\n" " { 0x300, 0 },\n" " { 0x320, 0 },\n" " { 0x340, 0 },\n" " { 0, 0 } /* end of table */\n" " };\n" "\n" " ...\n" " int port, i;\n" " ...\n" "\n" " port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);\n" " if(port !=0 ) {\n" " for(i=0; xxx_allports[i].port!=0; i++) {\n" " if(xxx_allports[i].used || xxx_allports[i].port != port)\n" " continue;\n" "\n" " /* found it */\n" " xxx_allports[i].used = 1;\n" " /* do probe on a known port */\n" " return xxx_really_probe(dev, port);\n" " }\n" " return ENXIO; /* port is unknown or already used */\n" " }\n" "\n" " /* we get here only if we need to guess the port */\n" " for(i=0; xxx_allports[i].port!=0; i++) {\n" " if(xxx_allports[i].used)\n" " continue;\n" "\n" " /* mark as used - even if we find nothing at this port\n" " * at least we won't probe it in future\n" " */\n" " xxx_allports[i].used = 1;\n" "\n" " error = xxx_really_probe(dev, xxx_allports[i].port);\n" " if(error == 0) /* found a device at that port */\n" " return 0;\n" " }\n" " /* probed all possible addresses, none worked */\n" " return ENXIO;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18383 msgid "" "Of course, normally the driver's identify() routine " "should be used for such things. But there may be one valid reason why it may " "be better to be done in probe(): if this probe would " "drive some other sensitive device crazy. The probe routines are ordered with " "consideration of the sensitive flag: the sensitive " "devices get probed first and the rest of the devices later. But the " "identify() routines are called before any probes, so " "they show no respect to the sensitive devices and may upset them." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18397 msgid "" "Now, after we got the starting port we need to set the port count (except " "for PnP devices) because the kernel does not have this information in the " "configuration file." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18403 #, no-wrap msgid "" "\n" " if(pnperror /* only for non-PnP devices */\n" " && bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0,\n" " XXX_PORT_COUNT)<0)\n" " return ENXIO;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18409 msgid "" "Finally allocate and activate a piece of port address space (special values " "of start and end mean use those we set by " "bus_set_resource()):" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18415 #, no-wrap msgid "" "\n" " sc->port0_rid = 0;\n" " sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,\n" " &sc->port0_rid,\n" " /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n" "\n" " if(sc->port0_r == NULL)\n" " return ENXIO;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18424 msgid "" "Now having access to the port-mapped registers we can poke the device in " "some way and check if it reacts like it is expected to. If it does not then " "there is probably some other device or no device at all at this address." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18431 msgid "" "Normally drivers do not set up the interrupt handlers until the attach " "routine. Instead they do probes in the polling mode using the " "DELAY() function for timeout. The probe routine must " "never hang forever, all the waits for the device must be done with timeouts. " "If the device does not respond within the time it is probably broken or " "misconfigured and the driver must return error. When determining the timeout " "interval give the device some extra time to be on the safe side: although " "DELAY() is supposed to delay for the same amount of " "time on any machine it has some margin of error, depending on the exact CPU." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18446 msgid "" "If the probe routine really wants to check that the interrupts really work " "it may configure and probe the interrupts too. But that is not recommended." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18452 #, no-wrap msgid "" "\n" " /* implemented in some very device-specific way */\n" " if(error = xxx_probe_ports(sc))\n" " goto bad; /* will deallocate the resources before returning */\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18458 msgid "" "The function xxx_probe_ports() may also set the device " "description depending on the exact model of device it discovers. But if " "there is only one supported device model this can be as well done in a " "hardcoded way. Of course, for the PnP devices the PnP support sets the " "description from the table automatically." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18468 #, no-wrap msgid "" " if(pnperror)\n" " device_set_desc(dev, \"Our device model 1234\");\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18472 msgid "" "Then the probe routine should either discover the ranges of all the " "resources by reading the device configuration registers or make sure that " "they were set explicitly by the user. We will consider it with an example of " "on-board memory. The probe routine should be as non-intrusive as possible, " "so allocation and check of functionality of the rest of resources (besides " "the ports) would be better left to the attach routine." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18483 msgid "" "The memory address may be specified in the kernel configuration file or on " "some devices it may be pre-configured in non-volatile configuration " "registers. If both sources are available and different, which one should be " "used? Probably if the user bothered to set the address explicitly in the " "kernel configuration file they know what they are doing and this one should " "take precedence. An example of implementation could be:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18493 #, no-wrap msgid "" "\n" " /* try to find out the config address first */\n" " sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /" "*rid*/);\n" " if(sc->mem0_p == 0) { /* nope, not specified by user */\n" " sc->mem0_p = xxx_read_mem0_from_device_config(sc);\n" "\n" "\n" " if(sc->mem0_p == 0)\n" " /* can't get it from device config registers either */\n" " goto bad;\n" " } else {\n" " if(xxx_set_mem0_address_on_device(sc) < 0)\n" " goto bad; /* device does not support that address */\n" " }\n" "\n" " /* just like the port, set the memory size,\n" " * for some devices the memory size would not be constant\n" " * but should be read from the device configuration registers " "instead\n" " * to accommodate different models of devices. Another option " "would\n" " * be to let the user set the memory size as \"msize\" " "configuration\n" " * resource which will be automatically handled by the ISA bus.\n" " */\n" " if(pnperror) { /* only for non-PnP devices */\n" " sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, " "0 /*rid*/);\n" " if(sc->mem0_size == 0) /* not specified by user */\n" " sc->mem0_size = " "xxx_read_mem0_size_from_device_config(sc);\n" "\n" " if(sc->mem0_size == 0) {\n" " /* suppose this is a very old model of device without\n" " * auto-configuration features and the user gave no " "preference,\n" " * so assume the minimalistic case\n" " * (of course, the real value will vary with the driver)\n" " */\n" " sc->mem0_size = 8*1024;\n" " }\n" "\n" " if(xxx_set_mem0_size_on_device(sc) < 0)\n" " goto bad; /* device does not support that size */\n" "\n" " if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,\n" " sc->mem0_p, sc->mem0_size)<0)\n" " goto bad;\n" " } else {\n" " sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, " "0 /*rid*/);\n" " } " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18539 msgid "Resources for IRQ and DRQ are easy to check by analogy." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18543 msgid "If all went well then release all the resources and return success." msgstr "" #. (itstool) path: sect1/programlisting #. (itstool) path: para/programlisting #: book.translate.xml:18547 book.translate.xml:18889 #, no-wrap msgid " xxx_free_resources(sc);\n" " return 0;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18550 msgid "" "Finally, handle the troublesome situations. All the resources should be " "deallocated before returning. We make use of the fact that before the " "structure softc is passed to us it gets zeroed out, so we can find out if " "some resource was allocated: then its descriptor is non-zero." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18558 #, no-wrap msgid "" " bad:\n" "\n" " xxx_free_resources(sc);\n" " if(error)\n" " return error;\n" " else /* exact error is unknown */\n" " return ENXIO;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18566 msgid "" "That would be all for the probe routine. Freeing of resources is done from " "multiple places, so it is moved to a function which may look like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18572 #, no-wrap msgid "" "static void\n" " xxx_free_resources(sc)\n" " struct xxx_softc *sc;\n" " {\n" " /* check every resource and free if not zero */\n" "\n" " /* interrupt handler */\n" " if(sc->intr_r) {\n" " bus_teardown_intr(sc->dev, sc->intr_r, sc-" ">intr_cookie);\n" " bus_release_resource(sc->dev, SYS_RES_IRQ, sc-" ">intr_rid,\n" " sc->intr_r);\n" " sc->intr_r = 0;\n" " }\n" "\n" " /* all kinds of memory maps we could have allocated */\n" " if(sc->data_p) {\n" " bus_dmamap_unload(sc->data_tag, sc->data_map);\n" " sc->data_p = 0;\n" " }\n" " if(sc->data) { /* sc->data_map may be legitimately " "equal to 0 */\n" " /* the map will also be freed */\n" " bus_dmamem_free(sc->data_tag, sc->data, sc-" ">data_map);\n" " sc->data = 0;\n" " }\n" " if(sc->data_tag) {\n" " bus_dma_tag_destroy(sc->data_tag);\n" " sc->data_tag = 0;\n" " }\n" "\n" " ... free other maps and tags if we have them ...\n" "\n" " if(sc->parent_tag) {\n" " bus_dma_tag_destroy(sc->parent_tag);\n" " sc->parent_tag = 0;\n" " }\n" "\n" " /* release all the bus resources */\n" " if(sc->mem0_r) {\n" " bus_release_resource(sc->dev, SYS_RES_MEMORY, sc-" ">mem0_rid,\n" " sc->mem0_r);\n" " sc->mem0_r = 0;\n" " }\n" " ...\n" " if(sc->port0_r) {\n" " bus_release_resource(sc->dev, SYS_RES_IOPORT, sc-" ">port0_rid,\n" " sc->port0_r);\n" " sc->port0_r = 0;\n" " }\n" " }" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18625 msgid "xxx_isa_attach" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18628 msgid "" "The attach routine actually connects the driver to the system if the probe " "routine returned success and the system had chosen to attach that driver. If " "the probe routine returned 0 then the attach routine may expect to receive " "the device structure softc intact, as it was set by the probe routine. Also " "if the probe routine returns 0 it may expect that the attach routine for " "this device shall be called at some point in the future. If the probe " "routine returns a negative value then the driver may make none of these " "assumptions." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18640 msgid "" "The attach routine returns 0 if it completed successfully or error code " "otherwise." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18644 msgid "" "The attach routine starts just like the probe routine, with getting some " "frequently used data into more accessible variables." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18649 #, no-wrap msgid "" " struct xxx_softc *sc = device_get_softc(dev);\n" " int unit = device_get_unit(dev);\n" " int error = 0;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18653 msgid "" "Then allocate and activate all the necessary resources. Because normally the " "port range will be released before returning from probe, it has to be " "allocated again. We expect that the probe routine had properly set all the " "resource ranges, as well as saved them in the structure softc. If the probe " "routine had left some resource allocated then it does not need to be " "allocated again (which would be considered an error)." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18663 #, no-wrap msgid "" " sc->port0_rid = 0;\n" " sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc-" ">port0_rid,\n" " /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n" "\n" " if(sc->port0_r == NULL)\n" " return ENXIO;\n" "\n" " /* on-board memory */\n" " sc->mem0_rid = 0;\n" " sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc-" ">mem0_rid,\n" " /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n" "\n" " if(sc->mem0_r == NULL)\n" " goto bad;\n" "\n" " /* get its virtual address */\n" " sc->mem0_v = rman_get_virtual(sc->mem0_r);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18681 msgid "" "The DMA request channel (DRQ) is allocated likewise. To initialize it use " "functions of the isa_dma*() family. For example:" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18686 msgid "isa_dmacascade(sc->drq0);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18688 msgid "" "The interrupt request line (IRQ) is a bit special. Besides allocation the " "driver's interrupt handler should be associated with it. Historically in the " "old ISA drivers the argument passed by the system to the interrupt handler " "was the device unit number. But in modern drivers the convention suggests " "passing the pointer to structure softc. The important reason is that when " "the structures softc are allocated dynamically then getting the unit number " "from softc is easy while getting softc from the unit number is difficult. " "Also this convention makes the drivers for different buses look more uniform " "and allows them to share the code: each bus gets its own probe, attach, " "detach and other bus-specific routines while the bulk of the driver code may " "be shared among them." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18704 #, no-wrap msgid "" "\n" " sc->intr_rid = 0;\n" " sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc-" ">intr_rid,\n" " /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);\n" "\n" " if(sc->intr_r == NULL)\n" " goto bad;\n" "\n" " /*\n" " * XXX_INTR_TYPE is supposed to be defined depending on the type " "of\n" " * the driver, for example as INTR_TYPE_CAM for a CAM driver\n" " */\n" " error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,\n" " (driver_intr_t *) xxx_intr, (void *) sc, &sc-" ">intr_cookie);\n" " if(error)\n" " goto bad;\n" "\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18724 msgid "" "If the device needs to make DMA to the main memory then this memory should " "be allocated like described before:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18728 #, no-wrap msgid "" " error=bus_dma_tag_create(NULL, /*alignment*/ 4,\n" " /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,\n" " /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ " "NULL,\n" " /*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,\n" " /*nsegments*/ BUS_SPACE_UNRESTRICTED,\n" " /*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,\n" " &sc->parent_tag);\n" " if(error)\n" " goto bad;\n" "\n" " /* many things get inherited from the parent tag\n" " * sc->data is supposed to point to the structure with the " "shared data,\n" " * for example for a ring buffer it could be:\n" " * struct {\n" " * u_short rd_pos;\n" " * u_short wr_pos;\n" " * char bf[XXX_RING_BUFFER_SIZE]\n" " * } *data;\n" " */\n" " error=bus_dma_tag_create(sc->parent_tag, 1,\n" " 0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,\n" " /*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,\n" " /*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,\n" " &sc->data_tag);\n" " if(error)\n" " goto bad;\n" "\n" " error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* " "flags*/ 0,\n" " &sc->data_map);\n" " if(error)\n" " goto bad;\n" "\n" " /* xxx_alloc_callback() just saves the physical address at\n" " * the pointer passed as its argument, in this case &sc-" ">data_p.\n" " * See details in the section on bus memory mapping.\n" " * It can be implemented like:\n" " *\n" " * static void\n" " * xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,\n" " * int nseg, int error)\n" " * {\n" " * *(bus_addr_t *)arg = seg[0].ds_addr;\n" " * }\n" " */\n" " bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc-" ">data,\n" " sizeof (* sc->data), xxx_alloc_callback, (void *) &sc-" ">data_p,\n" " /*flags*/0);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18777 msgid "" "After all the necessary resources are allocated the device should be " "initialized. The initialization may include testing that all the expected " "features are functional." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18781 #, no-wrap msgid "" " if(xxx_initialize(sc) < 0)\n" " goto bad; " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18785 msgid "" "The bus subsystem will automatically print on the console the device " "description set by probe. But if the driver wants to print some extra " "information about the device it may do so, for example:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18790 #, no-wrap msgid "" "\n" " device_printf(dev, \"has on-card FIFO buffer of %d bytes\\n\", sc-" ">fifosize);\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18794 msgid "" "If the initialization routine experiences any problems then printing " "messages about them before returning error is also recommended." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18798 msgid "" "The final step of the attach routine is attaching the device to its " "functional subsystem in the kernel. The exact way to do it depends on the " "type of the driver: a character device, a block device, a network device, a " "CAM SCSI bus device and so on." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18804 msgid "If all went well then return success." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18806 #, no-wrap msgid "" " error = xxx_attach_subsystem(sc);\n" " if(error)\n" " goto bad;\n" "\n" " return 0; " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18812 msgid "" "Finally, handle the troublesome situations. All the resources should be " "deallocated before returning an error. We make use of the fact that before " "the structure softc is passed to us it gets zeroed out, so we can find out " "if some resource was allocated: then its descriptor is non-zero." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18819 #, no-wrap msgid "" " bad:\n" "\n" " xxx_free_resources(sc);\n" " if(error)\n" " return error;\n" " else /* exact error is unknown */\n" " return ENXIO;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18827 msgid "That would be all for the attach routine." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18833 msgid "xxx_isa_detach" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18835 msgid "" "If this function is present in the driver and the driver is compiled as a " "loadable module then the driver gets the ability to be unloaded. This is an " "important feature if the hardware supports hot plug. But the ISA bus does " "not support hot plug, so this feature is not particularly important for the " "ISA devices. The ability to unload a driver may be useful when debugging it, " "but in many cases installation of the new version of the driver would be " "required only after the old version somehow wedges the system and a reboot " "will be needed anyway, so the efforts spent on writing the detach routine " "may not be worth it. Another argument that unloading would allow upgrading " "the drivers on a production machine seems to be mostly theoretical. " "Installing a new version of a driver is a dangerous operation which should " "never be performed on a production machine (and which is not permitted when " "the system is running in secure mode). Still, the detach routine may be " "provided for the sake of completeness." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18856 msgid "" "The detach routine returns 0 if the driver was successfully detached or the " "error code otherwise." msgstr "" #. (itstool) path: para/programlisting #: book.translate.xml:18870 #, no-wrap msgid "" " struct xxx_softc *sc = device_get_softc(dev);\n" " int error;\n" "\n" " error = xxx_detach_subsystem(sc);\n" " if(error)\n" " return error;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18861 msgid "" "The logic of detach is a mirror of the attach. The first thing to do is to " "detach the driver from its kernel subsystem. If the device is currently open " "then the driver has two choices: refuse to be detached or forcibly close and " "proceed with detach. The choice used depends on the ability of the " "particular kernel subsystem to do a forced close and on the preferences of " "the driver's author. Generally the forced close seems to be the preferred " "alternative. <_:programlisting-1/>" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18877 msgid "" "Next the driver may want to reset the hardware to some consistent state. " "That includes stopping any ongoing transfers, disabling the DMA channels and " "interrupts to avoid memory corruption by the device. For most of the drivers " "this is exactly what the shutdown routine does, so if it is included in the " "driver we can just call it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18885 msgid "xxx_isa_shutdown(dev);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18887 msgid "" "And finally release all the resources and return success. <_:programlisting-" "1/>" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18896 msgid "xxx_isa_shutdown" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18898 msgid "" "This routine is called when the system is about to be shut down. It is " "expected to bring the hardware to some consistent state. For most of the ISA " "devices no special action is required, so the function is not really " "necessary because the device will be re-initialized on reboot anyway. But " "some devices have to be shut down with a special procedure, to make sure " "that they will be properly detected after soft reboot (this is especially " "true for many devices with proprietary identification protocols). In any " "case disabling DMA and interrupts in the device registers and stopping any " "ongoing transfers is a good idea. The exact action depends on the hardware, " "so we do not consider it here in any detail." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18916 msgid "xxx_intr" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:18918 msgid "interrupt handler" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18920 msgid "" "The interrupt handler is called when an interrupt is received which may be " "from this particular device. The ISA bus does not support interrupt sharing " "(except in some special cases) so in practice if the interrupt handler is " "called then the interrupt almost for sure came from its device. Still, the " "interrupt handler must poll the device registers and make sure that the " "interrupt was generated by its device. If not it should just return." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18931 msgid "" "The old convention for the ISA drivers was getting the device unit number as " "an argument. This is obsolete, and the new drivers receive whatever argument " "was specified for them in the attach routine when calling " "bus_setup_intr(). By the new convention it should be " "the pointer to the structure softc. So the interrupt handler commonly starts " "as:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18941 #, no-wrap msgid "" "\n" " static void\n" " xxx_intr(struct xxx_softc *sc)\n" " {\n" "\n" " " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18948 msgid "" "It runs at the interrupt priority level specified by the interrupt type " "parameter of bus_setup_intr(). That means that all the " "other interrupts of the same type as well as all the software interrupts are " "disabled." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18956 msgid "To avoid races it is commonly written as a loop:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:18960 #, no-wrap msgid "" "\n" " while(xxx_interrupt_pending(sc)) {\n" " xxx_process_interrupt(sc);\n" " xxx_acknowledge_interrupt(sc);\n" " } " msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18966 msgid "" "The interrupt handler has to acknowledge interrupt to the device only but " "not to the interrupt controller, the system takes care of the latter." msgstr "" #. (itstool) path: chapter/title #: book.translate.xml:18982 msgid "PCI Devices" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:18984 msgid "PCI bus" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:18986 msgid "" "This chapter will talk about the FreeBSD mechanisms for writing a device " "driver for a device on a PCI bus." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:18990 msgid "Probe and Attach" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:18992 msgid "" "Information here about how the PCI bus code iterates through the unattached " "devices and see if a newly loaded kld will attach to any of them." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:18997 msgid "Sample Driver Source (mypci.c)" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:18999 #, no-wrap msgid "" "/*\n" " * Simple KLD to play with the PCI functions.\n" " *\n" " * Murray Stokely\n" " */\n" "\n" "#include <sys/param.h> /* defines used in kernel.h */\n" "#include <sys/module.h>\n" "#include <sys/systm.h>\n" "#include <sys/errno.h>\n" "#include <sys/kernel.h> /* types used in module initialization */\n" "#include <sys/conf.h> /* cdevsw struct */\n" "#include <sys/uio.h> /* uio struct */\n" "#include <sys/malloc.h>\n" "#include <sys/bus.h> /* structs, prototypes for pci bus stuff and " "DEVMETHOD macros! */\n" "\n" "#include <machine/bus.h>\n" "#include <sys/rman.h>\n" "#include <machine/resource.h>\n" "\n" "#include <dev/pci/pcivar.h> /* For pci_get macros! */\n" "#include <dev/pci/pcireg.h>\n" "\n" "/* The softc holds our per-instance data. */\n" "struct mypci_softc {\n" " device_t my_dev;\n" " struct cdev *my_cdev;\n" "};\n" "\n" "/* Function prototypes */\n" "static d_open_t mypci_open;\n" "static d_close_t mypci_close;\n" "static d_read_t mypci_read;\n" "static d_write_t mypci_write;\n" "\n" "/* Character device entry points */\n" "\n" "static struct cdevsw mypci_cdevsw = {\n" " .d_version = D_VERSION,\n" " .d_open = mypci_open,\n" " .d_close = mypci_close,\n" " .d_read = mypci_read,\n" " .d_write = mypci_write,\n" " .d_name = \"mypci\",\n" "};\n" "\n" "/*\n" " * In the cdevsw routines, we find our softc by using the si_drv1 member\n" " * of struct cdev. We set this variable to point to our softc in our\n" " * attach routine when we create the /dev entry.\n" " */\n" "\n" "int\n" "mypci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " /* Look up our softc. */\n" " sc = dev->si_drv1;\n" " device_printf(sc->my_dev, \"Opened successfully.\\n\");\n" " return (0);\n" "}\n" "\n" "int\n" "mypci_close(struct cdev *dev, int fflag, int devtype, struct thread *td)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " /* Look up our softc. */\n" " sc = dev->si_drv1;\n" " device_printf(sc->my_dev, \"Closed.\\n\");\n" " return (0);\n" "}\n" "\n" "int\n" "mypci_read(struct cdev *dev, struct uio *uio, int ioflag)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " /* Look up our softc. */\n" " sc = dev->si_drv1;\n" " device_printf(sc->my_dev, \"Asked to read %d bytes.\\n\", uio-" ">uio_resid);\n" " return (0);\n" "}\n" "\n" "int\n" "mypci_write(struct cdev *dev, struct uio *uio, int ioflag)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " /* Look up our softc. */\n" " sc = dev->si_drv1;\n" " device_printf(sc->my_dev, \"Asked to write %d bytes.\\n\", uio-" ">uio_resid);\n" " return (0);\n" "}\n" "\n" "/* PCI Support Functions */\n" "\n" "/*\n" " * Compare the device ID of this device against the IDs that this driver\n" " * supports. If there is a match, set the description and return success.\n" " */\n" "static int\n" "mypci_probe(device_t dev)\n" "{\n" "\n" " device_printf(dev, \"MyPCI Probe\\nVendor ID : 0x%x\\nDevice ID : " "0x%x\\n\",\n" " pci_get_vendor(dev), pci_get_device(dev));\n" "\n" " if (pci_get_vendor(dev) == 0x11c1) {\n" " printf(\"We've got the Winmodem, probe successful!\\n\");\n" " device_set_desc(dev, \"WinModem\");\n" " return (BUS_PROBE_DEFAULT);\n" " }\n" " return (ENXIO);\n" "}\n" "\n" "/* Attach function is only called if the probe is successful. */\n" "\n" "static int\n" "mypci_attach(device_t dev)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " printf(\"MyPCI Attach for : deviceID : 0x%x\\n\", pci_get_devid(dev));\n" "\n" " /* Look up our softc and initialize its fields. */\n" " sc = device_get_softc(dev);\n" " sc->my_dev = dev;\n" "\n" " /*\n" " * Create a /dev entry for this device. The kernel will assign us\n" " * a major number automatically. We use the unit number of this\n" " * device as the minor number and name the character device\n" " * \"mypci<unit>\".\n" " */\n" " sc->my_cdev = make_dev(&mypci_cdevsw, " "device_get_unit(dev),\n" " UID_ROOT, GID_WHEEL, 0600, \"mypci%u\", device_get_unit(dev));\n" " sc->my_cdev->si_drv1 = sc;\n" " printf(\"Mypci device loaded.\\n\");\n" " return (0);\n" "}\n" "\n" "/* Detach device. */\n" "\n" "static int\n" "mypci_detach(device_t dev)\n" "{\n" " struct mypci_softc *sc;\n" "\n" " /* Teardown the state in our softc created in our attach routine. */\n" " sc = device_get_softc(dev);\n" " destroy_dev(sc->my_cdev);\n" " printf(\"Mypci detach!\\n\");\n" " return (0);\n" "}\n" "\n" "/* Called during system shutdown after sync. */\n" "\n" "static int\n" "mypci_shutdown(device_t dev)\n" "{\n" "\n" " printf(\"Mypci shutdown!\\n\");\n" " return (0);\n" "}\n" "\n" "/*\n" " * Device suspend routine.\n" " */\n" "static int\n" "mypci_suspend(device_t dev)\n" "{\n" "\n" " printf(\"Mypci suspend!\\n\");\n" " return (0);\n" "}\n" "\n" "/*\n" " * Device resume routine.\n" " */\n" "static int\n" "mypci_resume(device_t dev)\n" "{\n" "\n" " printf(\"Mypci resume!\\n\");\n" " return (0);\n" "}\n" "\n" "static device_method_t mypci_methods[] = {\n" " /* Device interface */\n" " DEVMETHOD(device_probe, mypci_probe),\n" " DEVMETHOD(device_attach, mypci_attach),\n" " DEVMETHOD(device_detach, mypci_detach),\n" " DEVMETHOD(device_shutdown, mypci_shutdown),\n" " DEVMETHOD(device_suspend, mypci_suspend),\n" " DEVMETHOD(device_resume, mypci_resume),\n" "\n" " DEVMETHOD_END\n" "};\n" "\n" "static devclass_t mypci_devclass;\n" "\n" "DEFINE_CLASS_0(mypci, mypci_driver, mypci_methods, sizeof(struct " "mypci_softc));\n" "DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:19207 msgid "Makefile for Sample Driver" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19209 #, no-wrap msgid "" "# Makefile for mypci driver\n" "\n" "KMOD= mypci\n" "SRCS= mypci.c\n" "SRCS+= device_if.h bus_if.h pci_if.h\n" "\n" ".include <bsd.kmod.mk>" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19217 msgid "" "If you place the above source file and Makefile into a " "directory, you may run make to compile the sample driver. " "Additionally, you may run make load to load the driver " "into the currently running kernel and make unload to " "unload the driver after it is loaded." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:19227 msgid "Additional Resources" msgstr "" #. (itstool) path: listitem/simpara #: book.translate.xml:19229 msgid "" "PCI Special Interest Group" msgstr "" #. (itstool) path: listitem/simpara #: book.translate.xml:19232 msgid "PCI System Architecture, Fourth Edition by Tom Shanley, et al." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:19240 msgid "Bus Resources" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19242 msgid "PCI busresources" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19243 msgid "" "FreeBSD provides an object-oriented mechanism for requesting resources from " "a parent bus. Almost all devices will be a child member of some sort of bus " "(PCI, ISA, USB, SCSI, etc) and these devices need to acquire resources from " "their parent bus (such as memory segments, interrupt lines, or DMA channels)." "" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:19250 msgid "Base Address Registers" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:19252 msgid "" "PCI busBase Address Registers" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19254 msgid "" "To do anything particularly useful with a PCI device you will need to obtain " "the Base Address Registers (BARs) from the PCI " "Configuration space. The PCI-specific details of obtaining the BAR are " "abstracted in the bus_alloc_resource() function." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19260 msgid "" "For example, a typical driver might have something similar to this in the " "attach() function:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19263 #, no-wrap msgid "" " sc->bar0id = PCIR_BAR(0);\n" " sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc-" ">bar0id,\n" " 0, ~0, 1, RF_ACTIVE);\n" " if (sc->bar0res == NULL) {\n" " printf(\"Memory allocation of PCI base register 0 failed!\\n\");\n" " error = ENXIO;\n" " goto fail1;\n" " }\n" "\n" " sc->bar1id = PCIR_BAR(1);\n" " sc->bar1res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc-" ">bar1id,\n" " 0, ~0, 1, RF_ACTIVE);\n" " if (sc->bar1res == NULL) {\n" " printf(\"Memory allocation of PCI base register 1 failed!\\n\");\n" " error = ENXIO;\n" " goto fail2;\n" " }\n" " sc->bar0_bt = rman_get_bustag(sc->bar0res);\n" " sc->bar0_bh = rman_get_bushandle(sc->bar0res);\n" " sc->bar1_bt = rman_get_bustag(sc->bar1res);\n" " sc->bar1_bh = rman_get_bushandle(sc->bar1res);" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19285 msgid "" "Handles for each base address register are kept in the softc structure so that they can be used to write " "to the device later." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19289 msgid "" "These handles can then be used to read or write from the device registers " "with the bus_space_* functions. For example, a driver " "might contain a shorthand function to read from a board specific register " "like this:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19294 #, no-wrap msgid "" "uint16_t\n" "board_read(struct ni_softc *sc, uint16_t address)\n" "{\n" " return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);\n" "}\n" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19301 msgid "Similarly, one could write to the registers with:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19303 #, no-wrap msgid "" "void\n" "board_write(struct ni_softc *sc, uint16_t address, uint16_t value)\n" "{\n" " bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);\n" "}\n" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19310 msgid "" "These functions exist in 8bit, 16bit, and 32bit versions and you should use " "bus_space_{read|write}_{1|2|4} accordingly." msgstr "" #. (itstool) path: note/para #: book.translate.xml:19316 msgid "" "In FreeBSD 7.0 and later, you can use the bus_* " "functions instead of bus_space_*. The bus_* functions take a struct resource * pointer instead of " "a bus tag and handle. Thus, you could drop the bus tag and bus handle " "members from the softc and rewrite " "the board_read() function as:" msgstr "" #. (itstool) path: note/programlisting #: book.translate.xml:19325 #, no-wrap msgid "" "uint16_t\n" "board_read(struct ni_softc *sc, uint16_t address)\n" "{\n" " return (bus_read(sc->bar1res, address));\n" "}\n" msgstr "" #. (itstool) path: sect2/title #. (itstool) path: sect1/title #: book.translate.xml:19334 book.translate.xml:21146 msgid "Interrupts" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:19336 msgid "PCI businterrupts" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19337 msgid "" "Interrupts are allocated from the object-oriented bus code in a way similar " "to the memory resources. First an IRQ resource must be allocated from the " "parent bus, and then the interrupt handler must be set up to deal with this " "IRQ." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19342 msgid "" "Again, a sample from a device attach() function says " "more than words." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19346 #, no-wrap msgid "" "/* Get the IRQ resource */\n" "\n" " sc->irqid = 0x0;\n" " sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc-" ">irqid),\n" " 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);\n" " if (sc->irqres == NULL) {\n" " printf(\"IRQ allocation failed!\\n\");\n" " error = ENXIO;\n" " goto fail3;\n" " }\n" "\n" " /* Now we should set up the interrupt handler */\n" "\n" " error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_MISC,\n" " my_handler, sc, &(sc->handler));\n" " if (error) {\n" " printf(\"Couldn't set up irq\\n\");\n" " goto fail4;\n" " }\n" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19367 msgid "" "Some care must be taken in the detach routine of the driver. You must " "quiesce the device's interrupt stream, and remove the interrupt handler. " "Once bus_teardown_intr() has returned, you know that " "your interrupt handler will no longer be called and that all threads that " "might have been executing this interrupt handler have returned. Since this " "function can sleep, you must not hold any mutexes when calling this function." "" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:19381 msgid "PCI busDMA" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19382 msgid "" "This section is obsolete, and present only for historical reasons. The " "proper methods for dealing with these issues is to use the " "bus_space_dma*() functions instead. This paragraph can " "be removed when this section is updated to reflect that usage. However, at " "the moment, the API is in a bit of flux, so once that settles down, it would " "be good to update this section to reflect that." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19390 msgid "" "On the PC, peripherals that want to do bus-mastering DMA must deal with " "physical addresses. This is a problem since FreeBSD uses virtual memory and " "deals almost exclusively with virtual addresses. Fortunately, there is a " "function, vtophys() to help." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19396 #, no-wrap msgid "" "#include <vm/vm.h>\n" "#include <vm/pmap.h>\n" "\n" "#define vtophys(virtual_address) (...)\n" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19402 msgid "" "The solution is a bit different on the alpha however, and what we really " "want is a function called vtobus()." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:19406 #, no-wrap msgid "" "#if defined(__alpha__)\n" "#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)\n" "#else\n" "#define vtobus(va) vtophys(va)\n" "#endif\n" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:19416 msgid "Deallocating Resources" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:19418 msgid "" "It is very important to deallocate all of the resources that were allocated " "during attach(). Care must be taken to deallocate the " "correct stuff even on a failure condition so that the system will remain " "usable while your driver dies." msgstr "" #. (itstool) path: info/title #: book.translate.xml:19436 msgid "Common Access Method SCSI Controllers" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19450 msgid "SCSI" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19451 msgid "" "This document assumes that the reader has a general understanding of device " "drivers in FreeBSD and of the SCSI protocol. Much of the information in this " "document was extracted from the drivers:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19458 msgid "" "ncr (/sys/pci/ncr.c) by Wolfgang Stanglmeier and Stefan " "Esser" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19462 msgid "sym (/sys/dev/sym/sym_hipd.c) by Gerard Roudier" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19467 msgid "" "aic7xxx (/sys/dev/aic7xxx/aic7xxx.c) by Justin T. Gibbs" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19473 msgid "" "and from the CAM code itself (by Justin T. Gibbs, see /sys/cam/*). When some solution looked the most logical and was essentially " "verbatim extracted from the code by Justin T. Gibbs, I marked it as " "recommended." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19479 msgid "" "The document is illustrated with examples in pseudo-code. Although sometimes " "the examples have many details and look like real code, it is still pseudo-" "code. It was written to demonstrate the concepts in an understandable way. " "For a real driver other approaches may be more modular and efficient. It " "also abstracts from the hardware details, as well as issues that would cloud " "the demonstrated concepts or that are supposed to be described in the other " "chapters of the developers handbook. Such details are commonly shown as " "calls to functions with descriptive names, comments or pseudo-statements. " "Fortunately real life full-size examples with all the details can be found " "in the real drivers." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:19494 msgid "General Architecture" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19496 msgid "Common Access Method (CAM)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19500 msgid "" "CAM stands for Common Access Method. It is a generic way to address the I/O " "buses in a SCSI-like way. This allows a separation of the generic device " "drivers from the drivers controlling the I/O bus: for example the disk " "driver becomes able to control disks on both SCSI, IDE, and/or any other bus " "so the disk driver portion does not have to be rewritten (or copied and " "modified) for every new I/O bus. Thus the two most important active entities " "are:" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19509 msgid "CD-ROM" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19510 msgid "tape" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:19511 msgid "IDE" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19514 msgid "" "Peripheral Modules - a driver for peripheral devices " "(disk, tape, CD-ROM, etc.)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19520 msgid "" "SCSI Interface Modules (SIM) - a Host Bus Adapter " "drivers for connecting to an I/O bus such as SCSI or IDE." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19526 msgid "" "A peripheral driver receives requests from the OS, converts them to a " "sequence of SCSI commands and passes these SCSI commands to a SCSI Interface " "Module. The SCSI Interface Module is responsible for passing these commands " "to the actual hardware (or if the actual hardware is not SCSI but, for " "example, IDE then also converting the SCSI commands to the native commands " "of the hardware)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19534 msgid "" "Because we are interested in writing a SCSI adapter driver here, from this " "point on we will consider everything from the SIM standpoint." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19538 msgid "" "A typical SIM driver needs to include the following CAM-related header files:" "" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19541 #, no-wrap msgid "" "#include <cam/cam.h>\n" "#include <cam/cam_ccb.h>\n" "#include <cam/cam_sim.h>\n" "#include <cam/cam_xpt_sim.h>\n" "#include <cam/cam_debug.h>\n" "#include <cam/scsi/scsi_all.h>" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19548 msgid "" "The first thing each SIM driver must do is register itself with the CAM " "subsystem. This is done during the driver's xxx_attach() function (here and further xxx_ is used to denote the unique " "driver name prefix). The xxx_attach() function itself " "is called by the system bus auto-configuration code which we do not describe " "here." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19556 msgid "" "This is achieved in multiple steps: first it is necessary to allocate the " "queue of requests associated with this SIM:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19559 #, no-wrap msgid "" " struct cam_devq *devq;\n" "\n" " if(( devq = cam_simq_alloc(SIZE) )==NULL) {\n" " error; /* some code to handle the error */\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19565 msgid "" "Here SIZE is the size of the queue to be allocated, " "maximal number of requests it could contain. It is the number of requests " "that the SIM driver can handle in parallel on one SCSI card. Commonly it can " "be calculated as:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19571 #, no-wrap msgid "" "SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19573 msgid "Next we create a descriptor of our SIM:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19575 #, no-wrap msgid "" " struct cam_sim *sim;\n" "\n" " if(( sim = cam_sim_alloc(action_func, poll_func, driver_name,\n" " softc, unit, mtx, max_dev_transactions,\n" " max_tagged_dev_transactions, devq) )==NULL) {\n" " cam_simq_free(devq);\n" " error; /* some code to handle the error */\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19584 msgid "" "Note that if we are not able to create a SIM descriptor we free the devq also because we can do nothing else with " "it and we want to conserve memory." msgstr "" #. (itstool) path: para/indexterm #: book.translate.xml:19589 msgid "SCSIbus" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19588 msgid "" "If a SCSI card has multiple SCSI buses<_:indexterm-1/> on it then each bus " "requires its own cam_sim structure." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19593 msgid "" "An interesting question is what to do if a SCSI card has more than one SCSI " "bus, do we need one devq structure " "per card or per SCSI bus? The answer given in the comments to the CAM code " "is: either way, as the driver's author prefers." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19599 msgid "The arguments are:" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:19606 book.translate.xml:19796 msgid "" "static void xxx_action " "struct cam_sim *sim, union ccb *ccb " msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19603 msgid "" "action_func - pointer to the driver's " "xxx_action function. <_:funcsynopsis-1/>" msgstr "" #. (itstool) path: funcsynopsis/funcprototype #: book.translate.xml:19622 book.translate.xml:21047 msgid "" "static void xxx_poll " "struct cam_sim *sim " msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19619 msgid "" "poll_func - pointer to the driver's " "xxx_poll() <_:funcsynopsis-1/>" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19634 msgid "" "driver_name - the name of the actual driver, such as ncr or " "wds." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19640 msgid "" "softc - pointer to the driver's " "internal descriptor for this SCSI card. This pointer will be used by the " "driver in future to get private data." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19647 msgid "" "unit - the controller unit number, for example for controller mps0 this number will be 0" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19653 msgid "" "mtx - Lock associated with this SIM. For SIMs that don't know about locking, " "pass in Giant. For SIMs that do, pass in the lock used to guard this SIM's " "data structures. This lock will be held when xxx_action and xxx_poll are " "called." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19660 msgid "" "max_dev_transactions - maximal number of simultaneous transactions per SCSI " "target in the non-tagged mode. This value will be almost universally equal " "to 1, with possible exceptions only for the non-SCSI cards. Also the drivers " "that hope to take advantage by preparing one transaction while another one " "is executed may set it to 2 but this does not seem to be worth the " "complexity." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19670 msgid "" "max_tagged_dev_transactions - the same thing, but in the tagged mode. Tags " "are the SCSI way to initiate multiple transactions on a device: each " "transaction is assigned a unique tag and the transaction is sent to the " "device. When the device completes some transaction it sends back the result " "together with the tag so that the SCSI adapter (and the driver) can tell " "which transaction was completed. This argument is also known as the maximal " "tag depth. It depends on the abilities of the SCSI adapter." msgstr "" #. (itstool) path: para/indexterm #: book.translate.xml:19684 msgid "SCSIadapter" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19683 msgid "" "Finally we register the SCSI buses associated with our SCSI adapter<_:" "indexterm-1/>:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19686 #, no-wrap msgid "" " if(xpt_bus_register(sim, softc, bus_number) != CAM_SUCCESS) {\n" " cam_sim_free(sim, /*free_devq*/ TRUE);\n" " error; /* some code to handle the error */\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19691 msgid "" "If there is one devq structure per " "SCSI bus (i.e., we consider a card with multiple buses as multiple cards " "with one bus each) then the bus number will always be 0, otherwise each bus " "on the SCSI card should be get a distinct number. Each bus needs its own " "separate structure cam_sim." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19698 msgid "" "After that our controller is completely hooked to the CAM system. The value " "of devq can be discarded now: sim " "will be passed as an argument in all further calls from CAM and devq can be " "derived from it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19703 msgid "" "CAM provides the framework for such asynchronous events. Some events " "originate from the lower levels (the SIM drivers), some events originate " "from the peripheral drivers, some events originate from the CAM subsystem " "itself. Any driver can register callbacks for some types of the asynchronous " "events, so that it would be notified if these events occur." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19710 msgid "" "A typical example of such an event is a device reset. Each transaction and " "event identifies the devices to which it applies by the means of " "path. The target-specific events normally occur during a " "transaction with this device. So the path from that transaction may be re-" "used to report this event (this is safe because the event path is copied in " "the event reporting routine but not deallocated nor passed anywhere further)." " Also it is safe to allocate paths dynamically at any time including the " "interrupt routines, although that incurs certain overhead, and a possible " "problem with this approach is that there may be no free memory at that time. " "For a bus reset event we need to define a wildcard path including all " "devices on the bus. So we can create the path for the future bus reset " "events in advance and avoid problems with the future memory shortage:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19726 #, no-wrap msgid "" " struct cam_path *path;\n" "\n" " if(xpt_create_path(&path, /*periph*/NULL,\n" " cam_sim_path(sim), CAM_TARGET_WILDCARD,\n" " CAM_LUN_WILDCARD) != CAM_REQ_CMP) {\n" " xpt_bus_deregister(cam_sim_path(sim));\n" " cam_sim_free(sim, /*free_devq*/TRUE);\n" " error; /* some code to handle the error */\n" " }\n" "\n" " softc->wpath = path;\n" " softc->sim = sim;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19739 msgid "As you can see the path includes:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19743 msgid "ID of the peripheral driver (NULL here because we have none)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19748 msgid "ID of the SIM driver (cam_sim_path(sim))" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19753 msgid "" "SCSI target number of the device (CAM_TARGET_WILDCARD means all " "devices)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19758 msgid "" "SCSI LUN number of the subdevice (CAM_LUN_WILDCARD means all LUNs)" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19763 msgid "" "If the driver can not allocate this path it will not be able to work " "normally, so in that case we dismantle that SCSI bus." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19767 msgid "" "And we save the path pointer in the softc structure for future use. After that we save the value of sim (or " "we can also discard it on the exit from xxx_probe() if " "we wish)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19772 msgid "" "That is all for a minimalistic initialization. To do things right there is " "one more issue left." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19775 msgid "" "For a SIM driver there is one particularly interesting event: when a target " "device is considered lost. In this case resetting the SCSI negotiations with " "this device may be a good idea. So we register a callback for this event " "with CAM. The request is passed to CAM by requesting CAM action on a CAM " "control block for this type of request:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19782 #, no-wrap msgid "" " struct ccb_setasync csa;\n" "\n" " xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);\n" " csa.ccb_h.func_code = XPT_SASYNC_CB;\n" " csa.event_enable = AC_LOST_DEVICE;\n" " csa.callback = xxx_async;\n" " csa.callback_arg = sim;\n" " xpt_action((union ccb *)&csa);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19791 msgid "" "Now we take a look at the xxx_action() and " "xxx_poll() driver entry points." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19807 msgid "" "Do some action on request of the CAM subsystem. Sim describes the SIM for " "the request, CCB is the request itself. CCB stands for CAM Control " "Block. It is a union of many specific instances, each describing " "arguments for some type of transactions. All of these instances share the " "CCB header where the common part of arguments is stored." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19814 msgid "" "CAM supports the SCSI controllers working in both initiator (normal) mode and target (simulating a SCSI device) mode. Here we only " "consider the part relevant to the initiator mode." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19819 msgid "" "There are a few function and macros (in other words, methods) defined to " "access the public data in the struct sim:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19825 msgid "cam_sim_path(sim) - the path ID (see above)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19830 msgid "cam_sim_name(sim) - the name of the sim" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19835 msgid "" "cam_sim_softc(sim) - the pointer to the softc (driver " "private data) structure" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19840 msgid " cam_sim_unit(sim) - the unit number" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19845 msgid " cam_sim_bus(sim) - the bus ID" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19850 msgid "" "To identify the device, xxx_action() can get the unit " "number and pointer to its structure softc using these functions." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19854 msgid "" "The type of request is stored in ccb-" ">ccb_h.func_code. So generally xxx_action() consists of a big switch:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:19859 #, no-wrap msgid "" " struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);\n" " struct ccb_hdr *ccb_h = &ccb->ccb_h;\n" " int unit = cam_sim_unit(sim);\n" " int bus = cam_sim_bus(sim);\n" "\n" " switch(ccb_h->func_code) {\n" " case ...:\n" " ...\n" " default:\n" " ccb_h->status = CAM_REQ_INVALID;\n" " xpt_done(ccb);\n" " break;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19873 msgid "" "As can be seen from the default case (if an unknown command was received) " "the return code of the command is set into ccb->ccb_h.status and the completed CCB is " "returned back to CAM by calling xpt_done(ccb)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19879 msgid "" "xpt_done() does not have to be called from " "xxx_action(): For example an I/O request may be " "enqueued inside the SIM driver and/or its SCSI controller. Then when the " "device would post an interrupt signaling that the processing of this request " "is complete xpt_done() may be called from the interrupt " "handling routine." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19887 msgid "" "Actually, the CCB status is not only assigned as a return code but a CCB has " "some status all the time. Before CCB is passed to the " "xxx_action() routine it gets the status CCB_REQ_INPROG " "meaning that it is in progress. There are a surprising number of status " "values defined in /sys/cam/cam.h which should be able " "to represent the status of a request in great detail. More interesting yet, " "the status is in fact a bitwise or of an enumerated status " "value (the lower 6 bits) and possible additional flag-like bits (the upper " "bits). The enumerated values will be discussed later in more detail. The " "summary of them can be found in the Errors Summary section. The possible " "status flags are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19903 msgid "" "CAM_DEV_QFRZN - if the SIM driver gets a serious error " "(for example, the device does not respond to the selection or breaks the " "SCSI protocol) when processing a CCB it should freeze the request queue by " "calling xpt_freeze_simq(), return the other enqueued " "but not processed yet CCBs for this device back to the CAM queue, then set " "this flag for the troublesome CCB and call xpt_done(). " "This flag causes the CAM subsystem to unfreeze the queue after it handles " "the error." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19916 msgid "" "CAM_AUTOSNS_VALID - if the device returned an error " "condition and the flag CAM_DIS_AUTOSENSE is not set in CCB the SIM driver " "must execute the REQUEST SENSE command automatically to extract the sense " "(extended error information) data from the device. If this attempt was " "successful the sense data should be saved in the CCB and this flag set." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19926 msgid "" "CAM_RELEASE_SIMQ - like CAM_DEV_QFRZN but used in case " "there is some problem (or resource shortage) with the SCSI controller itself." " Then all the future requests to the controller should be stopped by " "xpt_freeze_simq(). The controller queue will be " "restarted after the SIM driver overcomes the shortage and informs CAM by " "returning some CCB with this flag set." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19937 msgid "" "CAM_SIM_QUEUED - when SIM puts a CCB into its request " "queue this flag should be set (and removed when this CCB gets dequeued " "before being returned back to CAM). This flag is not used anywhere in the " "CAM code now, so its purpose is purely diagnostic." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19945 msgid "CAM_QOS_VALID - The QOS data is now valid." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19950 msgid "" "The function xxx_action() is not allowed to sleep, so " "all the synchronization for resource access must be done using SIM or device " "queue freezing. Besides the aforementioned flags the CAM subsystem provides " "functions xpt_release_simq() and " "xpt_release_devq() to unfreeze the queues directly, " "without passing a CCB to CAM." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:19958 msgid "The CCB header contains the following fields:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19962 msgid "path - path ID for the request" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19967 msgid "target_id - target device ID for the request" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19972 msgid "target_lun - LUN ID of the target device" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19977 msgid "" "timeout - timeout interval for this command, in " "milliseconds" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19982 msgid "" "timeout_ch - a convenience place for the SIM driver to " "store the timeout handle (the CAM subsystem itself does not make any " "assumptions about it)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:19989 msgid "" "flags - various bits of information about the request " "spriv_ptr0, spriv_ptr1 - fields reserved for private use by the SIM driver " "(such as linking to the SIM queues or SIM private control blocks); actually, " "they exist as unions: spriv_ptr0 and spriv_ptr1 have the type (void *), " "spriv_field0 and spriv_field1 have the type unsigned long, sim_priv." "entries[0].bytes and sim_priv.entries[1].bytes are byte arrays of the size " "consistent with the other incarnations of the union and sim_priv.bytes is " "one array, twice bigger." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:20002 msgid "" "The recommended way of using the SIM private fields of CCB is to define some " "meaningful names for them and use these meaningful names in the driver, like:" "" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:20006 #, no-wrap msgid "" "#define ccb_some_meaningful_name sim_priv.entries[0].bytes\n" "#define ccb_hcb spriv_ptr1 /* for hardware control block */" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:20009 msgid "The most common initiator mode requests are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20013 msgid "XPT_SCSI_IO - execute an I/O transaction" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20016 msgid "" "The instance struct ccb_scsiio csio of the union ccb is used " "to transfer the arguments. They are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20022 msgid "" "cdb_io - pointer to the SCSI command buffer or the " "buffer itself" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20027 msgid "cdb_len - SCSI command length" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20032 msgid "" "data_ptr - pointer to the data buffer (gets a bit " "complicated if scatter/gather is used)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20038 msgid "dxfer_len - length of the data to transfer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20043 msgid "" "sglist_cnt - counter of the scatter/gather segments" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20048 msgid "scsi_status - place to return the SCSI status" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20053 msgid "" "sense_data - buffer for the SCSI sense information if " "the command returns an error (the SIM driver is supposed to run the REQUEST " "SENSE command automatically in this case if the CCB flag CAM_DIS_AUTOSENSE " "is not set)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20061 msgid "" "sense_len - the length of that buffer (if it happens to " "be higher than size of sense_data the SIM driver must silently assume the " "smaller value) resid, sense_resid - if the transfer of data or SCSI sense " "returned an error these are the returned counters of the residual (not " "transferred) data. They do not seem to be especially meaningful, so in a " "case when they are difficult to compute (say, counting bytes in the SCSI " "controller's FIFO buffer) an approximate value will do as well. For a " "successfully completed transfer they must be set to zero." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20076 msgid "tag_action - the kind of tag to use:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20081 msgid "CAM_TAG_ACTION_NONE - do not use tags for this transaction" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20086 msgid "" "MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - value equal to the " "appropriate tag message (see /sys/cam/scsi/scsi_message.h); this gives only " "the tag type, the SIM driver must assign the tag value itself" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20096 msgid "The general logic of handling this request is the following:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20099 msgid "" "The first thing to do is to check for possible races, to make sure that the " "command did not get aborted when it was sitting in the queue:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20103 #, no-wrap msgid "" " struct ccb_scsiio *csio = &ccb->csio;\n" "\n" " if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {\n" " xpt_done(ccb);\n" " return;\n" " }" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20110 msgid "Also we check that the device is supported at all by our controller:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20113 #, no-wrap msgid "" " if(ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID\n" " || cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {\n" " ccb_h->status = CAM_TID_INVALID;\n" " xpt_done(ccb);\n" " return;\n" " }\n" " if(ccb_h->target_lun > OUR_MAX_SUPPORTED_LUN) {\n" " ccb_h->status = CAM_LUN_INVALID;\n" " xpt_done(ccb);\n" " return;\n" " }" msgstr "" #. (itstool) path: para/indexterm #: book.translate.xml:20127 msgid "hardware control block" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20125 msgid "" "Then allocate whatever data structures (such as card-dependent hardware " "control block<_:indexterm-1/>) we need to process this request. If we can " "not then freeze the SIM queue and remember that we have a pending operation, " "return the CCB back and ask CAM to re-queue it. Later when the resources " "become available the SIM queue must be unfrozen by returning a ccb with the " "CAM_SIMQ_RELEASE bit set in its status. Otherwise, if all " "went well, link the CCB with the hardware control block (HCB) and mark it as " "queued." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20138 #, no-wrap msgid "" " struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);\n" "\n" " if(hcb == NULL) {\n" " softc->flags |= RESOURCE_SHORTAGE;\n" " xpt_freeze_simq(sim, /*count*/1);\n" " ccb_h->status = CAM_REQUEUE_REQ;\n" " xpt_done(ccb);\n" " return;\n" " }\n" "\n" " hcb->ccb = ccb; ccb_h->ccb_hcb = (void *)hcb;\n" " ccb_h->status |= CAM_SIM_QUEUED;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20151 msgid "" "Extract the target data from CCB into the hardware control block. Check if " "we are asked to assign a tag and if yes then generate an unique tag and " "build the SCSI tag messages. The SIM driver is also responsible for " "negotiations with the devices to set the maximal mutually supported bus " "width, synchronous rate and offset." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20158 #, no-wrap msgid "" " hcb->target = ccb_h->target_id; hcb->lun = ccb_h-" ">target_lun;\n" " generate_identify_message(hcb);\n" " if( ccb_h->tag_action != CAM_TAG_ACTION_NONE )\n" " generate_unique_tag_message(hcb, ccb_h->tag_action);\n" " if( !target_negotiated(hcb) )\n" " generate_negotiation_messages(hcb);" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20165 msgid "" "Then set up the SCSI command. The command storage may be specified in the " "CCB in many interesting ways, specified by the CCB flags. The command buffer " "can be contained in CCB or pointed to, in the latter case the pointer may be " "physical or virtual. Since the hardware commonly needs physical address we " "always convert the address to the physical one, typically using the busdma " "API." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20173 msgid "" "In case if a physical address is requested it is OK to return the CCB with " "the status CAM_REQ_INVALID, the current drivers do " "that. If necessary a physical address can be also converted or mapped back " "to a virtual address but with big pain, so we do not do that." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20180 #, no-wrap msgid "" " if(ccb_h->flags & CAM_CDB_POINTER) {\n" " /* CDB is a pointer */\n" " if(!(ccb_h->flags & CAM_CDB_PHYS)) {\n" " /* CDB pointer is virtual */\n" " hcb->cmd = vtobus(csio->cdb_io.cdb_ptr);\n" " } else {\n" " /* CDB pointer is physical */\n" " hcb->cmd = csio->cdb_io.cdb_ptr ;\n" " }\n" " } else {\n" " /* CDB is in the ccb (buffer) */\n" " hcb->cmd = vtobus(csio->cdb_io.cdb_bytes);\n" " }\n" " hcb->cmdlen = csio->cdb_len;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20195 msgid "" "Now it is time to set up the data. Again, the data storage may be specified " "in the CCB in many interesting ways, specified by the CCB flags. First we " "get the direction of the data transfer. The simplest case is if there is no " "data to transfer:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20201 #, no-wrap msgid "" " int dir = (ccb_h->flags & CAM_DIR_MASK);\n" "\n" " if (dir == CAM_DIR_NONE)\n" " goto end_data;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20206 msgid "" "Then we check if the data is in one chunk or in a scatter-gather list, and " "the addresses are physical or virtual. The SCSI controller may be able to " "handle only a limited number of chunks of limited length. If the request " "hits this limitation we return an error. We use a special function to return " "the CCB to handle in one place the HCB resource shortages. The functions to " "add chunks are driver-dependent, and here we leave them without detailed " "implementation. See description of the SCSI command (CDB) handling for the " "details on the address-translation issues. If some variation is too " "difficult or impossible to implement with a particular card it is OK to " "return the status CAM_REQ_INVALID. Actually, it seems " "like the scatter-gather ability is not used anywhere in the CAM code now. " "But at least the case for a single non-scattered virtual buffer must be " "implemented, it is actively used by CAM." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20224 #, no-wrap msgid "" " int rv;\n" "\n" " initialize_hcb_for_data(hcb);\n" "\n" " if((!(ccb_h->flags & CAM_SCATTER_VALID)) {\n" " /* single buffer */\n" " if(!(ccb_h->flags & CAM_DATA_PHYS)) {\n" " rv = add_virtual_chunk(hcb, csio->data_ptr, csio-" ">dxfer_len, dir);\n" " }\n" " } else {\n" " rv = add_physical_chunk(hcb, csio->data_ptr, csio-" ">dxfer_len, dir);\n" " }\n" " } else {\n" " int i;\n" " struct bus_dma_segment *segs;\n" " segs = (struct bus_dma_segment *)csio->data_ptr;\n" "\n" " if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) {\n" " /* The SG list pointer is physical */\n" " rv = setup_hcb_for_physical_sg_list(hcb, segs, csio-" ">sglist_cnt);\n" " } else if (!(ccb_h->flags & CAM_DATA_PHYS)) {\n" " /* SG buffer pointers are virtual */\n" " for (i = 0; i < csio->sglist_cnt; i++) {\n" " rv = add_virtual_chunk(hcb, segs[i].ds_addr,\n" " segs[i].ds_len, dir);\n" " if (rv != CAM_REQ_CMP)\n" " break;\n" " }\n" " } else {\n" " /* SG buffer pointers are physical */\n" " for (i = 0; i < csio->sglist_cnt; i++) {\n" " rv = add_physical_chunk(hcb, segs[i].ds_addr,\n" " segs[i].ds_len, dir);\n" " if (rv != CAM_REQ_CMP)\n" " break;\n" " }\n" " }\n" " }\n" " if(rv != CAM_REQ_CMP) {\n" " /* we expect that add_*_chunk() functions return CAM_REQ_CMP\n" " * if they added a chunk successfully, CAM_REQ_TOO_BIG if\n" " * the request is too big (too many bytes or too many chunks),\n" " * CAM_REQ_INVALID in case of other troubles\n" " */\n" " free_hcb_and_ccb_done(hcb, ccb, rv);\n" " return;\n" " }\n" " end_data:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20273 msgid "" "If disconnection is disabled for this CCB we pass this information to the " "hcb:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20276 #, no-wrap msgid "" " if(ccb_h->flags & CAM_DIS_DISCONNECT)\n" " hcb_disable_disconnect(hcb);" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20279 msgid "" "If the controller is able to run REQUEST SENSE command all by itself then " "the value of the flag CAM_DIS_AUTOSENSE should also be passed to it, to " "prevent automatic REQUEST SENSE if the CAM subsystem does not want it." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20284 msgid "" "The only thing left is to set up the timeout, pass our hcb to the hardware " "and return, the rest will be done by the interrupt handler (or timeout " "handler)." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20288 #, no-wrap msgid "" " ccb_h->timeout_ch = timeout(xxx_timeout, (caddr_t) hcb,\n" " (ccb_h->timeout * hz) / 1000); /* convert milliseconds to ticks */" "\n" " put_hcb_into_hardware_queue(hcb);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20293 msgid "And here is a possible implementation of the function returning CCB:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20296 #, no-wrap msgid "" " static void\n" " free_hcb_and_ccb_done(struct xxx_hcb *hcb, union ccb *ccb, u_int32_t " "status)\n" " {\n" " struct xxx_softc *softc = hcb->softc;\n" "\n" " ccb->ccb_h.ccb_hcb = 0;\n" " if(hcb != NULL) {\n" " untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch);\n" " /* we're about to free a hcb, so the shortage has ended */\n" " if(softc->flags & RESOURCE_SHORTAGE) {\n" " softc->flags &= ~RESOURCE_SHORTAGE;\n" " status |= CAM_RELEASE_SIMQ;\n" " }\n" " free_hcb(hcb); /* also removes hcb from any internal lists */\n" " }\n" " ccb->ccb_h.status = status |\n" " (ccb->ccb_h.status & ~(CAM_STATUS_MASK|CAM_SIM_QUEUED));\n" " xpt_done(ccb);\n" " }" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20318 msgid "" "XPT_RESET_DEV - send the SCSI BUS DEVICE RESET message to a device" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20321 msgid "" "There is no data transferred in CCB except the header and the most " "interesting argument of it is target_id. Depending on the controller " "hardware a hardware control block just like for the XPT_SCSI_IO request may " "be constructed (see XPT_SCSI_IO request description) and sent to the " "controller or the SCSI controller may be immediately programmed to send this " "RESET message to the device or this request may be just not supported (and " "return the status CAM_REQ_INVALID). Also on " "completion of the request all the disconnected transactions for this target " "must be aborted (probably in the interrupt routine)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20334 msgid "" "Also all the current negotiations for the target are lost on reset, so they " "might be cleaned too. Or they clearing may be deferred, because anyway the " "target would request re-negotiation on the next transaction." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20342 msgid "" "XPT_RESET_BUS - send the RESET signal to the SCSI bus" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20345 msgid "" "No arguments are passed in the CCB, the only interesting argument is the " "SCSI bus indicated by the struct sim pointer." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20349 msgid "" "A minimalistic implementation would forget the SCSI negotiations for all the " "devices on the bus and return the status CAM_REQ_CMP." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20353 msgid "" "The proper implementation would in addition actually reset the SCSI bus " "(possible also reset the SCSI controller) and mark all the CCBs being " "processed, both those in the hardware queue and those being disconnected, as " "done with the status CAM_SCSI_BUS_RESET. Like:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20359 #, no-wrap msgid "" " int targ, lun;\n" " struct xxx_hcb *h, *hh;\n" " struct ccb_trans_settings neg;\n" " struct cam_path *path;\n" "\n" " /* The SCSI bus reset may take a long time, in this case its completion\n" " * should be checked by interrupt or timeout. But for simplicity\n" " * we assume here that it is really fast.\n" " */\n" " reset_scsi_bus(softc);\n" "\n" " /* drop all enqueued CCBs */\n" " for(h = softc->first_queued_hcb; h != NULL; h = hh) {\n" " hh = h->next;\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n" " }\n" "\n" " /* the clean values of negotiations to report */\n" " neg.bus_width = 8;\n" " neg.sync_period = neg.sync_offset = 0;\n" " neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n" " | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n" "\n" " /* drop all disconnected CCBs and clean negotiations */\n" " for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n" " clean_negotiations(softc, targ);\n" "\n" " /* report the event if possible */\n" " if(xpt_create_path(&path, /*periph*/NULL,\n" " cam_sim_path(sim), targ,\n" " CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n" " xpt_async(AC_TRANSFER_NEG, path, &neg);\n" " xpt_free_path(path);\n" " }\n" "\n" " for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n" " for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h = " "hh) {\n" " hh=h->next;\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n" " }\n" " }\n" "\n" " ccb->ccb_h.status = CAM_REQ_CMP;\n" " xpt_done(ccb);\n" "\n" " /* report the event */\n" " xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20408 msgid "" "Implementing the SCSI bus reset as a function may be a good idea because it " "would be re-used by the timeout function as a last resort if the things go " "wrong." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20415 msgid "XPT_ABORT - abort the specified CCB" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20418 msgid "" "The arguments are transferred in the instance struct ccb_abort cab of the union ccb. The only argument field in it is:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20422 msgid "abort_ccb - pointer to the CCB to be aborted" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20425 msgid "" "If the abort is not supported just return the status CAM_UA_ABORT. This is " "also the easy way to minimally implement this call, return CAM_UA_ABORT in " "any case." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20429 msgid "" "The hard way is to implement this request honestly. First check that abort " "applies to a SCSI transaction:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20432 #, no-wrap msgid "" " struct ccb *abort_ccb;\n" " abort_ccb = ccb->cab.abort_ccb;\n" "\n" " if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n" " ccb->ccb_h.status = CAM_UA_ABORT;\n" " xpt_done(ccb);\n" " return;\n" " }" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20441 msgid "" "Then it is necessary to find this CCB in our queue. This can be done by " "walking the list of all our hardware control blocks in search for one " "associated with this CCB:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20446 #, no-wrap msgid "" " struct xxx_hcb *hcb, *h;\n" "\n" " hcb = NULL;\n" "\n" " /* We assume that softc->first_hcb is the head of the list of all\n" " * HCBs associated with this bus, including those enqueued for\n" " * processing, being processed by hardware and disconnected ones.\n" " */\n" " for(h = softc->first_hcb; h != NULL; h = h->next) {\n" " if(h->ccb == abort_ccb) {\n" " hcb = h;\n" " break;\n" " }\n" " }\n" "\n" " if(hcb == NULL) {\n" " /* no such CCB in our queue */\n" " ccb->ccb_h.status = CAM_PATH_INVALID;\n" " xpt_done(ccb);\n" " return;\n" " }\n" "\n" " hcb=found_hcb;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20470 msgid "" "Now we look at the current processing status of the HCB. It may be either " "sitting in the queue waiting to be sent to the SCSI bus, being transferred " "right now, or disconnected and waiting for the result of the command, or " "actually completed by hardware but not yet marked as done by software. To " "make sure that we do not get in any races with hardware we mark the HCB as " "being aborted, so that if this HCB is about to be sent to the SCSI bus the " "SCSI controller will see this flag and skip it." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20480 #, no-wrap msgid "" " int hstatus;\n" "\n" " /* shown as a function, in case special action is needed to make\n" " * this flag visible to hardware\n" " */\n" " set_hcb_flags(hcb, HCB_BEING_ABORTED);\n" "\n" " abort_again:\n" "\n" " hstatus = get_hcb_status(hcb);\n" " switch(hstatus) {\n" " case HCB_SITTING_IN_QUEUE:\n" " remove_hcb_from_hardware_queue(hcb);\n" " /* FALLTHROUGH */\n" " case HCB_COMPLETED:\n" " /* this is an easy case */\n" " free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);\n" " break;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20499 msgid "" "If the CCB is being transferred right now we would like to signal to the " "SCSI controller in some hardware-dependent way that we want to abort the " "current transfer. The SCSI controller would set the SCSI ATTENTION signal " "and when the target responds to it send an ABORT message. We also reset the " "timeout to make sure that the target is not sleeping forever. If the command " "would not get aborted in some reasonable time like 10 seconds the timeout " "routine would go ahead and reset the whole SCSI bus. Because the command " "will be aborted in some reasonable time we can just return the abort request " "now as successfully completed, and mark the aborted CCB as aborted (but not " "mark it as done yet)." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20513 #, no-wrap msgid "" " case HCB_BEING_TRANSFERRED:\n" " untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h." "timeout_ch);\n" " abort_ccb->ccb_h.timeout_ch =\n" " timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n" " abort_ccb->ccb_h.status = CAM_REQ_ABORTED;\n" " /* ask the controller to abort that HCB, then generate\n" " * an interrupt and stop\n" " */\n" " if(signal_hardware_to_abort_hcb_and_stop(hcb) < 0) {\n" " /* oops, we missed the race with hardware, this transaction\n" " * got off the bus before we aborted it, try again */\n" " goto abort_again;\n" " }\n" "\n" " break;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20529 msgid "" "If the CCB is in the list of disconnected then set it up as an abort request " "and re-queue it at the front of hardware queue. Reset the timeout and report " "the abort request to be completed." msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20534 #, no-wrap msgid "" " case HCB_DISCONNECTED:\n" " untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h." "timeout_ch);\n" " abort_ccb->ccb_h.timeout_ch =\n" " timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);\n" " put_abort_message_into_hcb(hcb);\n" " put_hcb_at_the_front_of_hardware_queue(hcb);\n" " break;\n" " }\n" " ccb->ccb_h.status = CAM_REQ_CMP;\n" " xpt_done(ccb);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20546 msgid "" "That is all for the ABORT request, although there is one more issue. Because " "the ABORT message cleans all the ongoing transactions on a LUN we have to " "mark all the other active transactions on this LUN as aborted. That should " "be done in the interrupt routine, after the transaction gets aborted." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20553 msgid "" "Implementing the CCB abort as a function may be quite a good idea, this " "function can be re-used if an I/O transaction times out. The only difference " "would be that the timed out transaction would return the status " "CAM_CMD_TIMEOUT for the timed out request. Then the case XPT_ABORT would be " "small, like that:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20560 #, no-wrap msgid "" " case XPT_ABORT:\n" " struct ccb *abort_ccb;\n" " abort_ccb = ccb->cab.abort_ccb;\n" "\n" " if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {\n" " ccb->ccb_h.status = CAM_UA_ABORT;\n" " xpt_done(ccb);\n" " return;\n" " }\n" " if(xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) < 0)\n" " /* no such CCB in our queue */\n" " ccb->ccb_h.status = CAM_PATH_INVALID;\n" " else\n" " ccb->ccb_h.status = CAM_REQ_CMP;\n" " xpt_done(ccb);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20579 msgid "" "XPT_SET_TRAN_SETTINGS - explicitly set values of SCSI " "transfer settings" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20582 msgid "" "The arguments are transferred in the instance struct " "ccb_trans_setting cts of the union ccb:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20588 msgid "" "valid - a bitmask showing which settings should be " "updated:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20593 msgid "" "CCB_TRANS_SYNC_RATE_VALID - synchronous transfer rate" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20598 msgid "CCB_TRANS_SYNC_OFFSET_VALID - synchronous offset" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20603 msgid "CCB_TRANS_BUS_WIDTH_VALID - bus width" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20608 msgid "" "CCB_TRANS_DISC_VALID - set enable/disable disconnection" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20613 msgid "" "CCB_TRANS_TQ_VALID - set enable/disable tagged queuing" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20618 msgid "" "flags - consists of two parts, binary arguments and " "identification of sub-operations. The binary arguments are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20624 msgid "CCB_TRANS_DISC_ENB - enable disconnection" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20629 msgid "CCB_TRANS_TAG_ENB - enable tagged queuing" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20636 msgid "the sub-operations are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20640 msgid "" "CCB_TRANS_CURRENT_SETTINGS - change the current " "negotiations" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20645 msgid "" "CCB_TRANS_USER_SETTINGS - remember the desired user " "values sync_period, sync_offset - self-explanatory, if sync_offset==0 then " "the asynchronous mode is requested bus_width - bus width, in bits (not " "bytes)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20655 msgid "" "Two sets of negotiated parameters are supported, the user settings and the " "current settings. The user settings are not really used much in the SIM " "drivers, this is mostly just a piece of memory where the upper levels can " "store (and later recall) its ideas about the parameters. Setting the user " "parameters does not cause re-negotiation of the transfer rates. But when the " "SCSI controller does a negotiation it must never set the values higher than " "the user parameters, so it is essentially the top boundary." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20666 msgid "" "The current settings are, as the name says, current. Changing them means " "that the parameters must be re-negotiated on the next transfer. Again, these " "new current settings are not supposed to be forced on the " "device, just they are used as the initial step of negotiations. Also they " "must be limited by actual capabilities of the SCSI controller: for example, " "if the SCSI controller has 8-bit bus and the request asks to set 16-bit wide " "transfers this parameter must be silently truncated to 8-bit transfers " "before sending it to the device." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20678 msgid "" "One caveat is that the bus width and synchronous parameters are per target " "while the disconnection and tag enabling parameters are per lun." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20682 msgid "" "The recommended implementation is to keep 3 sets of negotiated (bus width " "and synchronous transfer) parameters:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20688 msgid "user - the user set, as above" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20693 msgid "current - those actually in effect" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20698 msgid "" "goal - those requested by setting of the " "current parameters" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20704 msgid "The code looks like:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20706 #, no-wrap msgid "" " struct ccb_trans_settings *cts;\n" " int targ, lun;\n" " int flags;\n" "\n" " cts = &ccb->cts;\n" " targ = ccb_h->target_id;\n" " lun = ccb_h->target_lun;\n" " flags = cts->flags;\n" " if(flags & CCB_TRANS_USER_SETTINGS) {\n" " if(flags & CCB_TRANS_SYNC_RATE_VALID)\n" " softc->user_sync_period[targ] = cts->sync_period;\n" " if(flags & CCB_TRANS_SYNC_OFFSET_VALID)\n" " softc->user_sync_offset[targ] = cts->sync_offset;\n" " if(flags & CCB_TRANS_BUS_WIDTH_VALID)\n" " softc->user_bus_width[targ] = cts->bus_width;\n" "\n" " if(flags & CCB_TRANS_DISC_VALID) {\n" " softc->user_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n" " softc->user_tflags[targ][lun] |= flags & " "CCB_TRANS_DISC_ENB;\n" " }\n" " if(flags & CCB_TRANS_TQ_VALID) {\n" " softc->user_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n" " softc->user_tflags[targ][lun] |= flags & " "CCB_TRANS_TQ_ENB;\n" " }\n" " }\n" " if(flags & CCB_TRANS_CURRENT_SETTINGS) {\n" " if(flags & CCB_TRANS_SYNC_RATE_VALID)\n" " softc->goal_sync_period[targ] =\n" " max(cts->sync_period, OUR_MIN_SUPPORTED_PERIOD);\n" " if(flags & CCB_TRANS_SYNC_OFFSET_VALID)\n" " softc->goal_sync_offset[targ] =\n" " min(cts->sync_offset, OUR_MAX_SUPPORTED_OFFSET);\n" " if(flags & CCB_TRANS_BUS_WIDTH_VALID)\n" " softc->goal_bus_width[targ] = min(cts->bus_width, " "OUR_BUS_WIDTH);\n" "\n" " if(flags & CCB_TRANS_DISC_VALID) {\n" " softc->current_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;\n" " softc->current_tflags[targ][lun] |= flags & " "CCB_TRANS_DISC_ENB;\n" " }\n" " if(flags & CCB_TRANS_TQ_VALID) {\n" " softc->current_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;\n" " softc->current_tflags[targ][lun] |= flags & " "CCB_TRANS_TQ_ENB;\n" " }\n" " }\n" " ccb->ccb_h.status = CAM_REQ_CMP;\n" " xpt_done(ccb);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20754 msgid "" "Then when the next I/O request will be processed it will check if it has to " "re-negotiate, for example by calling the function target_negotiated(hcb). It " "can be implemented like this:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20759 #, no-wrap msgid "" " int\n" " target_negotiated(struct xxx_hcb *hcb)\n" " {\n" " struct softc *softc = hcb->softc;\n" " int targ = hcb->targ;\n" "\n" " if( softc->current_sync_period[targ] != softc-" ">goal_sync_period[targ]\n" " || softc->current_sync_offset[targ] != softc-" ">goal_sync_offset[targ]\n" " || softc->current_bus_width[targ] != softc-" ">goal_bus_width[targ] )\n" " return 0; /* FALSE */\n" " else\n" " return 1; /* TRUE */\n" " }" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20773 msgid "" "After the values are re-negotiated the resulting values must be assigned to " "both current and goal parameters, so for future I/O transactions the current " "and goal parameters would be the same and target_negotiated() would return TRUE. When the card is initialized (in " "xxx_attach()) the current negotiation values must be " "initialized to narrow asynchronous mode, the goal and current values must be " "initialized to the maximal values supported by controller." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20784 msgid "" "XPT_GET_TRAN_SETTINGS - get values of SCSI transfer " "settings" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20787 msgid "" "This operations is the reverse of XPT_SET_TRAN_SETTINGS. Fill up the CCB " "instance struct ccb_trans_setting cts with data as requested " "by the flags CCB_TRANS_CURRENT_SETTINGS or CCB_TRANS_USER_SETTINGS (if both " "are set then the existing drivers return the current settings). Set all the " "bits in the valid field." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20795 msgid "" "XPT_CALC_GEOMETRY - calculate logical (BIOS)<_:" "indexterm-1/> geometry of the disk" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20799 msgid "" "The arguments are transferred in the instance struct " "ccb_calc_geometry ccg of the union ccb:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20806 msgid "" "block_size - input, block (A.K.A sector) size in bytes" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20811 msgid "volume_size - input, volume size in bytes" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20816 msgid "cylinders - output, logical cylinders" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20821 msgid "heads - output, logical heads" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20826 msgid "" "secs_per_track - output, logical sectors per track" msgstr "" #. (itstool) path: para/indexterm #: book.translate.xml:20832 msgid "SCSI BIOS" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20831 msgid "" "If the returned geometry differs much enough from what the SCSI controller " "BIOS<_:indexterm-1/> thinks and a disk on this SCSI controller is used as " "bootable the system may not be able to boot. The typical calculation example " "taken from the aic7xxx driver is:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20838 #, no-wrap msgid "" " struct ccb_calc_geometry *ccg;\n" " u_int32_t size_mb;\n" " u_int32_t secs_per_cylinder;\n" " int extended;\n" "\n" " ccg = &ccb->ccg;\n" " size_mb = ccg->volume_size\n" " / ((1024L * 1024L) / ccg->block_size);\n" " extended = check_cards_EEPROM_for_extended_geometry(softc);\n" "\n" " if (size_mb > 1024 && extended) {\n" " ccg->heads = 255;\n" " ccg->secs_per_track = 63;\n" " } else {\n" " ccg->heads = 64;\n" " ccg->secs_per_track = 32;\n" " }\n" " secs_per_cylinder = ccg->heads * ccg->secs_per_track;\n" " ccg->cylinders = ccg->volume_size / secs_per_cylinder;\n" " ccb->ccb_h.status = CAM_REQ_CMP;\n" " xpt_done(ccb);\n" " return;" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20861 msgid "" "This gives the general idea, the exact calculation depends on the quirks of " "the particular BIOS. If BIOS provides no way set the extended " "translation flag in EEPROM this flag should normally be assumed " "equal to 1. Other popular geometries are:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:20867 #, no-wrap msgid "" " 128 heads, 63 sectors - Symbios controllers\n" " 16 heads, 63 sectors - old controllers" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20870 msgid "" "Some system BIOSes and SCSI BIOSes fight with each other with variable " "success, for example a combination of Symbios 875/895 SCSI and Phoenix BIOS " "can give geometry 128/63 after power up and 255/63 after a hard reset or " "soft reboot." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20878 msgid "" "XPT_PATH_INQ - path inquiry, in other words get the SIM " "driver and SCSI controller (also known as HBA - Host Bus Adapter) properties" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20882 msgid "" "The properties are returned in the instance struct ccb_pathinq cpi of the union ccb:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20888 msgid "version_num - the SIM driver version number, now all drivers use 1" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20893 msgid "hba_inquiry - bitmask of features supported by the controller:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20898 msgid "PI_MDP_ABLE - supports MDP message (something from SCSI3?)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20903 msgid "PI_WIDE_32 - supports 32 bit wide SCSI" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20908 msgid "PI_WIDE_16 - supports 16 bit wide SCSI" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20913 msgid "PI_SDTR_ABLE - can negotiate synchronous transfer rate" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20918 msgid "PI_LINKED_CDB - supports linked commands" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20923 msgid "PI_TAG_ABLE - supports tagged commands" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20928 msgid "" "PI_SOFT_RST - supports soft reset alternative (hard reset and soft reset are " "mutually exclusive within a SCSI bus)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20934 msgid "target_sprt - flags for target mode support, 0 if unsupported" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20939 msgid "hba_misc - miscellaneous controller features:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20944 msgid "PIM_SCANHILO - bus scans from high ID to low ID" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20949 msgid "PIM_NOREMOVE - removable devices not included in scan" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20954 msgid "PIM_NOINITIATOR - initiator role not supported" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20959 msgid "PIM_NOBUSRESET - user has disabled initial BUS RESET" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20964 msgid "" "hba_eng_cnt - mysterious HBA engine count, something related to compression, " "now is always set to 0" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20969 msgid "vuhba_flags - vendor-unique flags, unused now" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20973 msgid "" "max_target - maximal supported target ID (7 for 8-bit bus, 15 for 16-bit " "bus, 127 for Fibre Channel)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20979 msgid "" "max_lun - maximal supported LUN ID (7 for older SCSI controllers, 63 for " "newer ones)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20984 msgid "async_flags - bitmask of installed Async handler, unused now" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20989 msgid "hpath_id - highest Path ID in the subsystem, unused now" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20994 msgid "unit_number - the controller unit number, cam_sim_unit(sim)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:20999 msgid "bus_id - the bus number, cam_sim_bus(sim)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21003 msgid "initiator_id - the SCSI ID of the controller itself" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21008 msgid "" "base_transfer_speed - nominal transfer speed in KB/s for asynchronous narrow " "transfers, equals to 3300 for SCSI" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21014 msgid "" "sim_vid - SIM driver's vendor id, a zero-terminated string of maximal length " "SIM_IDLEN including the terminating zero" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21020 msgid "" "hba_vid - SCSI controller's vendor id, a zero-terminated string of maximal " "length HBA_IDLEN including the terminating zero" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21026 msgid "" "dev_name - device driver name, a zero-terminated string of maximal length " "DEV_IDLEN including the terminating zero, equal to cam_sim_name(sim)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21032 msgid "" "The recommended way of setting the string fields is using strncpy, like:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:21035 #, no-wrap msgid " strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21037 msgid "" "After setting the values set the status to CAM_REQ_CMP and mark the CCB as " "done." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:21044 msgid "Polling" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21057 msgid "" "The poll function is used to simulate the interrupts when the interrupt " "subsystem is not functioning (for example, when the system has crashed and " "is creating the system dump). The CAM subsystem sets the proper interrupt " "level before calling the poll routine. So all it needs to do is to call the " "interrupt routine (or the other way around, the poll routine may be doing " "the real action and the interrupt routine would just call the poll routine). " "Why bother about a separate function then? Because of different calling " "conventions. The xxx_poll routine gets the struct " "cam_sim pointer as its argument when the PCI interrupt routine by common " "convention gets pointer to the struct xxx_softc and the ISA interrupt routine gets just " "the device unit number. So the poll routine would normally look as:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21073 #, no-wrap msgid "" "static void\n" "xxx_poll(struct cam_sim *sim)\n" "{\n" " xxx_intr((struct xxx_softc *)cam_sim_softc(sim)); /* for PCI device */\n" "}" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21079 msgid "or" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21081 #, no-wrap msgid "" "static void\n" "xxx_poll(struct cam_sim *sim)\n" "{\n" " xxx_intr(cam_sim_unit(sim)); /* for ISA device */\n" "}" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:21089 msgid "Asynchronous Events" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21091 msgid "" "If an asynchronous event callback has been set up then the callback function " "should be defined." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21094 #, no-wrap msgid "" "static void\n" "ahc_async(void *callback_arg, u_int32_t code, struct cam_path *path, void " "*arg)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21099 msgid "callback_arg - the value supplied when registering the callback" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21104 msgid "code - identifies the type of event" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21108 msgid "path - identifies the devices to which the event applies" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21113 msgid "arg - event-specific argument" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21117 msgid "Implementation for a single type of event, AC_LOST_DEVICE, looks like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21120 #, no-wrap msgid "" " struct xxx_softc *softc;\n" " struct cam_sim *sim;\n" " int targ;\n" " struct ccb_trans_settings neg;\n" "\n" " sim = (struct cam_sim *)callback_arg;\n" " softc = (struct xxx_softc *)cam_sim_softc(sim);\n" " switch (code) {\n" " case AC_LOST_DEVICE:\n" " targ = xpt_path_target_id(path);\n" " if(targ <= OUR_MAX_SUPPORTED_TARGET) {\n" " clean_negotiations(softc, targ);\n" " /* send indication to CAM */\n" " neg.bus_width = 8;\n" " neg.sync_period = neg.sync_offset = 0;\n" " neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n" " | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n" " xpt_async(AC_TRANSFER_NEG, path, &neg);\n" " }\n" " break;\n" " default:\n" " break;\n" " }" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:21148 msgid "SCSIinterrupts" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21150 msgid "" "The exact type of the interrupt routine depends on the type of the " "peripheral bus (PCI, ISA and so on) to which the SCSI controller is " "connected." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21154 msgid "" "The interrupt routines of the SIM drivers run at the interrupt level splcam. " "So splcam() should be used in the driver to synchronize " "activity between the interrupt routine and the rest of the driver (for a " "multiprocessor-aware driver things get yet more interesting but we ignore " "this case here). The pseudo-code in this document happily ignores the " "problems of synchronization. The real code must not ignore them. A simple-" "minded approach is to set splcam() on the entry to the " "other routines and reset it on return thus protecting them by one big " "critical section. To make sure that the interrupt level will be always " "restored a wrapper function can be defined, like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21167 #, no-wrap msgid "" " static void\n" " xxx_action(struct cam_sim *sim, union ccb *ccb)\n" " {\n" " int s;\n" " s = splcam();\n" " xxx_action1(sim, ccb);\n" " splx(s);\n" " }\n" "\n" " static void\n" " xxx_action1(struct cam_sim *sim, union ccb *ccb)\n" " {\n" " ... process the request ...\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21182 msgid "" "This approach is simple and robust but the problem with it is that " "interrupts may get blocked for a relatively long time and this would " "negatively affect the system's performance. On the other hand the functions " "of the spl() family have rather high overhead, so vast " "amount of tiny critical sections may not be good either." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21189 msgid "" "The conditions handled by the interrupt routine and the details depend very " "much on the hardware. We consider the set of typical " "conditions." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21193 msgid "" "First, we check if a SCSI reset was encountered on the bus (probably caused " "by another SCSI controller on the same SCSI bus). If so we drop all the " "enqueued and disconnected requests, report the events and re-initialize our " "SCSI controller. It is important that during this initialization the " "controller will not issue another reset or else two controllers on the same " "SCSI bus could ping-pong resets forever. The case of fatal controller error/" "hang could be handled in the same place, but it will probably need also " "sending RESET signal to the SCSI bus to reset the status of the connections " "with the SCSI devices." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21205 #, no-wrap msgid "" " int fatal=0;\n" " struct ccb_trans_settings neg;\n" " struct cam_path *path;\n" "\n" " if( detected_scsi_reset(softc)\n" " || (fatal = detected_fatal_controller_error(softc)) ) {\n" " int targ, lun;\n" " struct xxx_hcb *h, *hh;\n" "\n" " /* drop all enqueued CCBs */\n" " for(h = softc->first_queued_hcb; h != NULL; h = hh) {\n" " hh = h->next;\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n" " }\n" "\n" " /* the clean values of negotiations to report */\n" " neg.bus_width = 8;\n" " neg.sync_period = neg.sync_offset = 0;\n" " neg.valid = (CCB_TRANS_BUS_WIDTH_VALID\n" " | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);\n" "\n" " /* drop all disconnected CCBs and clean negotiations */\n" " for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {\n" " clean_negotiations(softc, targ);\n" "\n" " /* report the event if possible */\n" " if(xpt_create_path(&path, /*periph*/NULL,\n" " cam_sim_path(sim), targ,\n" " CAM_LUN_WILDCARD) == CAM_REQ_CMP) {\n" " xpt_async(AC_TRANSFER_NEG, path, &neg);\n" " xpt_free_path(path);\n" " }\n" "\n" " for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n" " for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h =" " hh) {\n" " hh=h->next;\n" " if(fatal)\n" " free_hcb_and_ccb_done(h, h->ccb, " "CAM_UNREC_HBA_ERROR);\n" " else\n" " free_hcb_and_ccb_done(h, h->ccb, " "CAM_SCSI_BUS_RESET);\n" " }\n" " }\n" "\n" " /* report the event */\n" " xpt_async(AC_BUS_RESET, softc->wpath, NULL);\n" "\n" " /* re-initialization may take a lot of time, in such case\n" " * its completion should be signaled by another interrupt or\n" " * checked on timeout - but for simplicity we assume here that\n" " * it is really fast\n" " */\n" " if(!fatal) {\n" " reinitialize_controller_without_scsi_reset(softc);\n" " } else {\n" " reinitialize_controller_with_scsi_reset(softc);\n" " }\n" " schedule_next_hcb(softc);\n" " return;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21265 msgid "" "If interrupt is not caused by a controller-wide condition then probably " "something has happened to the current hardware control block. Depending on " "the hardware there may be other non-HCB-related events, we just do not " "consider them here. Then we analyze what happened to this HCB:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21271 #, no-wrap msgid "" " struct xxx_hcb *hcb, *h, *hh;\n" " int hcb_status, scsi_status;\n" " int ccb_status;\n" " int targ;\n" " int lun_to_freeze;\n" "\n" " hcb = get_current_hcb(softc);\n" " if(hcb == NULL) {\n" " /* either stray interrupt or something went very wrong\n" " * or this is something hardware-dependent\n" " */\n" " handle as necessary;\n" " return;\n" " }\n" "\n" " targ = hcb->target;\n" " hcb_status = get_status_of_current_hcb(softc);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21289 msgid "" "First we check if the HCB has completed and if so we check the returned SCSI " "status." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21292 #, no-wrap msgid "" " if(hcb_status == COMPLETED) {\n" " scsi_status = get_completion_status(hcb);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21295 msgid "" "Then look if this status is related to the REQUEST SENSE command and if so " "handle it in a simple way." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21298 #, no-wrap msgid "" " if(hcb->flags & DOING_AUTOSENSE) {\n" " if(scsi_status == GOOD) { /* autosense was successful */\n" " hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;\n" " free_hcb_and_ccb_done(hcb, hcb->ccb, " "CAM_SCSI_STATUS_ERROR);\n" " } else {\n" " autosense_failed:\n" " free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_AUTOSENSE_FAIL);\n" " }\n" " schedule_next_hcb(softc);\n" " return;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21310 msgid "" "Else the command itself has completed, pay more attention to details. If " "auto-sense is not disabled for this CCB and the command has failed with " "sense data then run REQUEST SENSE command to receive that data." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21315 #, no-wrap msgid "" " hcb->ccb->csio.scsi_status = scsi_status;\n" " calculate_residue(hcb);\n" "\n" " if( (hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)==0\n" " && ( scsi_status == CHECK_CONDITION\n" " || scsi_status == COMMAND_TERMINATED) ) {\n" " /* start auto-SENSE */\n" " hcb->flags |= DOING_AUTOSENSE;\n" " setup_autosense_command_in_hcb(hcb);\n" " restart_current_hcb(softc);\n" " return;\n" " }\n" " if(scsi_status == GOOD)\n" " free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_REQ_CMP);\n" " else\n" " free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);\n" " schedule_next_hcb(softc);\n" " return;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21335 msgid "" "One typical thing would be negotiation events: negotiation messages received " "from a SCSI target (in answer to our negotiation attempt or by target's " "initiative) or the target is unable to negotiate (rejects our negotiation " "messages or does not answer them)." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21341 #, no-wrap msgid "" " switch(hcb_status) {\n" " case TARGET_REJECTED_WIDE_NEG:\n" " /* revert to 8-bit bus */\n" " softc->current_bus_width[targ] = softc->goal_bus_width[targ] = " "8;\n" " /* report the event */\n" " neg.bus_width = 8;\n" " neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n" " xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n" " continue_current_hcb(softc);\n" " return;\n" " case TARGET_ANSWERED_WIDE_NEG:\n" " {\n" " int wd;\n" "\n" " wd = get_target_bus_width_request(softc);\n" " if(wd <= softc->goal_bus_width[targ]) {\n" " /* answer is acceptable */\n" " softc->current_bus_width[targ] =\n" " softc->goal_bus_width[targ] = neg.bus_width = wd;\n" "\n" " /* report the event */\n" " neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n" " xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, " "&neg);\n" " } else {\n" " prepare_reject_message(hcb);\n" " }\n" " }\n" " continue_current_hcb(softc);\n" " return;\n" " case TARGET_REQUESTED_WIDE_NEG:\n" " {\n" " int wd;\n" "\n" " wd = get_target_bus_width_request(softc);\n" " wd = min (wd, OUR_BUS_WIDTH);\n" " wd = min (wd, softc->user_bus_width[targ]);\n" "\n" " if(wd != softc->current_bus_width[targ]) {\n" " /* the bus width has changed */\n" " softc->current_bus_width[targ] =\n" " softc->goal_bus_width[targ] = neg.bus_width = wd;\n" "\n" " /* report the event */\n" " neg.valid = CCB_TRANS_BUS_WIDTH_VALID;\n" " xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, " "&neg);\n" " }\n" " prepare_width_nego_rsponse(hcb, wd);\n" " }\n" " continue_current_hcb(softc);\n" " return;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21393 msgid "" "Then we handle any errors that could have happened during auto-sense in the " "same simple-minded way as before. Otherwise we look closer at the details " "again." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21397 #, no-wrap msgid "" " if(hcb->flags & DOING_AUTOSENSE)\n" " goto autosense_failed;\n" "\n" " switch(hcb_status) {" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21402 msgid "" "The next event we consider is unexpected disconnect. Which is considered " "normal after an ABORT or BUS DEVICE RESET message and abnormal in other " "cases." msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21406 #, no-wrap msgid "" " case UNEXPECTED_DISCONNECT:\n" " if(requested_abort(hcb)) {\n" " /* abort affects all commands on that target+LUN, so\n" " * mark all disconnected HCBs on that target+LUN as aborted too\n" " */\n" " for(h = softc->first_discon_hcb[hcb->target][hcb->lun];\n" " h != NULL; h = hh) {\n" " hh=h->next;\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_REQ_ABORTED);\n" " }\n" " ccb_status = CAM_REQ_ABORTED;\n" " } else if(requested_bus_device_reset(hcb)) {\n" " int lun;\n" "\n" " /* reset affects all commands on that target, so\n" " * mark all disconnected HCBs on that target+LUN as reset\n" " */\n" "\n" " for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++)\n" " for(h = softc->first_discon_hcb[hcb->target][lun];\n" " h != NULL; h = hh) {\n" " hh=h->next;\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);\n" " }\n" "\n" " /* send event */\n" " xpt_async(AC_SENT_BDR, hcb->ccb->ccb_h.path_id, NULL);\n" "\n" " /* this was the CAM_RESET_DEV request itself, it is completed */\n" " ccb_status = CAM_REQ_CMP;\n" " } else {\n" " calculate_residue(hcb);\n" " ccb_status = CAM_UNEXP_BUSFREE;\n" " /* request the further code to freeze the queue */\n" " hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n" " lun_to_freeze = hcb->lun;\n" " }\n" " break;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21445 msgid "" "If the target refuses to accept tags we notify CAM about that and return " "back all commands for this LUN:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21448 #, no-wrap msgid "" " case TAGS_REJECTED:\n" " /* report the event */\n" " neg.flags = 0 & ~CCB_TRANS_TAG_ENB;\n" " neg.valid = CCB_TRANS_TQ_VALID;\n" " xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);\n" "\n" " ccb_status = CAM_MSG_REJECT_REC;\n" " /* request the further code to freeze the queue */\n" " hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n" " lun_to_freeze = hcb->lun;\n" " break;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21460 msgid "" "Then we check a number of other conditions, with processing basically " "limited to setting the CCB status:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21463 #, no-wrap msgid "" " case SELECTION_TIMEOUT:\n" " ccb_status = CAM_SEL_TIMEOUT;\n" " /* request the further code to freeze the queue */\n" " hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n" " lun_to_freeze = CAM_LUN_WILDCARD;\n" " break;\n" " case PARITY_ERROR:\n" " ccb_status = CAM_UNCOR_PARITY;\n" " break;\n" " case DATA_OVERRUN:\n" " case ODD_WIDE_TRANSFER:\n" " ccb_status = CAM_DATA_RUN_ERR;\n" " break;\n" " default:\n" " /* all other errors are handled in a generic way */\n" " ccb_status = CAM_REQ_CMP_ERR;\n" " /* request the further code to freeze the queue */\n" " hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;\n" " lun_to_freeze = CAM_LUN_WILDCARD;\n" " break;\n" " }" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21485 msgid "" "Then we check if the error was serious enough to freeze the input queue " "until it gets proceeded and do so if it is:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21488 #, no-wrap msgid "" " if(hcb->ccb->ccb_h.status & CAM_DEV_QFRZN) {\n" " /* freeze the queue */\n" " xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);\n" "\n" " /* re-queue all commands for this target/LUN back to CAM */\n" "\n" " for(h = softc->first_queued_hcb; h != NULL; h = hh) {\n" " hh = h->next;\n" "\n" " if(targ == h->targ\n" " && (lun_to_freeze == CAM_LUN_WILDCARD || lun_to_freeze ==" " h->lun) )\n" " free_hcb_and_ccb_done(h, h->ccb, CAM_REQUEUE_REQ);\n" " }\n" " }\n" " free_hcb_and_ccb_done(hcb, hcb->ccb, ccb_status);\n" " schedule_next_hcb(softc);\n" " return;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21506 msgid "" "This concludes the generic interrupt handling although specific controllers " "may require some additions." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:21511 msgid "Errors Summary" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:21513 msgid "SCSIerrors" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21515 msgid "" "When executing an I/O request many things may go wrong. The reason of error " "can be reported in the CCB status with great detail. Examples of use are " "spread throughout this document. For completeness here is the summary of " "recommended responses for the typical error conditions:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21523 msgid "" "CAM_RESRC_UNAVAIL - some resource is temporarily " "unavailable and the SIM driver cannot generate an event when it will become " "available. An example of this resource would be some intra-controller " "hardware resource for which the controller does not generate an interrupt " "when it becomes available." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21532 msgid "" "CAM_UNCOR_PARITY - unrecovered parity error occurred" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21537 msgid "" "CAM_DATA_RUN_ERR - data overrun or unexpected data " "phase (going in other direction than specified in CAM_DIR_MASK) or odd " "transfer length for wide transfer" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21544 msgid "" "CAM_SEL_TIMEOUT - selection timeout occurred (target " "does not respond)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21549 msgid "" "CAM_CMD_TIMEOUT - command timeout occurred (the timeout " "function ran)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21554 msgid "CAM_SCSI_STATUS_ERROR - the device returned error" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21559 msgid "" "CAM_AUTOSENSE_FAIL - the device returned error and the " "REQUEST SENSE COMMAND failed" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21564 msgid "" "CAM_MSG_REJECT_REC - MESSAGE REJECT message was " "received" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21569 msgid "CAM_SCSI_BUS_RESET - received SCSI bus reset" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21574 msgid "" "CAM_REQ_CMP_ERR - impossible SCSI phase " "occurred or something else as weird or just a generic error if further " "detail is not available" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21581 msgid "" "CAM_UNEXP_BUSFREE - unexpected disconnect occurred" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21586 msgid "" "CAM_BDR_SENT - BUS DEVICE RESET message was sent to the " "target" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21591 msgid "" "CAM_UNREC_HBA_ERROR - unrecoverable Host Bus Adapter " "Error" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21596 msgid "" "CAM_REQ_TOO_BIG - the request was too large for this " "controller" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21601 msgid "" "CAM_REQUEUE_REQ - this request should be re-queued to " "preserve transaction ordering. This typically occurs when the SIM recognizes " "an error that should freeze the queue and must place other queued requests " "for the target at the sim level back into the XPT queue. Typical cases of " "such errors are selection timeouts, command timeouts and other like " "conditions. In such cases the troublesome command returns the status " "indicating the error, the and the other commands which have not be sent to " "the bus yet get re-queued." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21614 msgid "" "CAM_LUN_INVALID - the LUN ID in the request is not " "supported by the SCSI controller" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21619 msgid "" "CAM_TID_INVALID - the target ID in the request is not " "supported by the SCSI controller" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:21626 msgid "Timeout Handling" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21628 msgid "" "When the timeout for an HCB expires that request should be aborted, just " "like with an XPT_ABORT request. The only difference is that the returned " "status of aborted request should be CAM_CMD_TIMEOUT instead of " "CAM_REQ_ABORTED (that is why implementation of the abort better be done as a " "function). But there is one more possible problem: what if the abort request " "itself will get stuck? In this case the SCSI bus should be reset, just like " "with an XPT_RESET_BUS request (and the idea about implementing it as a " "function called from both places applies here too). Also we should reset the " "whole SCSI bus if a device reset request got stuck. So after all the timeout " "function would look like:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:21641 #, no-wrap msgid "" "static void\n" "xxx_timeout(void *arg)\n" "{\n" " struct xxx_hcb *hcb = (struct xxx_hcb *)arg;\n" " struct xxx_softc *softc;\n" " struct ccb_hdr *ccb_h;\n" "\n" " softc = hcb->softc;\n" " ccb_h = &hcb->ccb->ccb_h;\n" "\n" " if(hcb->flags & HCB_BEING_ABORTED\n" " || ccb_h->func_code == XPT_RESET_DEV) {\n" " xxx_reset_bus(softc);\n" " } else {\n" " xxx_abort_ccb(hcb->ccb, CAM_CMD_TIMEOUT);\n" " }\n" "}" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21659 msgid "" "When we abort a request all the other disconnected requests to the same " "target/LUN get aborted too. So there appears a question, should we return " "them with status CAM_REQ_ABORTED or CAM_CMD_TIMEOUT? The current drivers use " "CAM_CMD_TIMEOUT. This seems logical because if one request got timed out " "then probably something really bad is happening to the device, so if they " "would not be disturbed they would time out by themselves." msgstr "" #. (itstool) path: info/title #: book.translate.xml:21677 msgid "USB Devices" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:21680 msgid "" " Nick Hibma Written by " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:21689 msgid "" " Murray Stokely Modifications for Handbook made by " msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:21702 msgid "Universal Serial Bus (USB)" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:21704 msgid "NetBSD" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21706 msgid "" "The Universal Serial Bus (USB) is a new way of attaching devices to personal " "computers. The bus architecture features two-way communication and has been " "developed as a response to devices becoming smarter and requiring more " "interaction with the host. USB support is included in all current PC " "chipsets and is therefore available in all recently built PCs. Apple's " "introduction of the USB-only iMac has been a major incentive for hardware " "manufacturers to produce USB versions of their devices. The future PC " "specifications specify that all legacy connectors on PCs should be replaced " "by one or more USB connectors, providing generic plug and play capabilities. " "Support for USB hardware was available at a very early stage in NetBSD and " "was developed by Lennart Augustsson for the NetBSD project. The code has " "been ported to FreeBSD and we are currently maintaining a shared code base. " "For the implementation of the USB subsystem a number of features of USB are " "important." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21723 msgid "" "Lennart Augustsson has done most of the implementation of the USB " "support for the NetBSD project. Many thanks for this incredible amount of " "work. Many thanks also to Ardy and Dirk for their comments and proofreading " "of this paper." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21732 msgid "" "Devices connect to ports on the computer directly or on devices called hubs, " "forming a treelike device structure." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21738 msgid "The devices can be connected and disconnected at run time." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21743 msgid "Devices can suspend themselves and trigger resumes of the host system" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21748 msgid "" "As the devices can be powered from the bus, the host software has to keep " "track of power budgets for each hub." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21754 msgid "" "Different quality of service requirements by the different device types " "together with the maximum of 126 devices that can be connected to the same " "bus, require proper scheduling of transfers on the shared bus to take full " "advantage of the 12Mbps bandwidth available. (over 400Mbps with USB 2.0)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21763 msgid "" "Devices are intelligent and contain easily accessible information about " "themselves" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21769 msgid "" "The development of drivers for the USB subsystem and devices connected to it " "is supported by the specifications that have been developed and will be " "developed. These specifications are publicly available from the USB home " "pages. Apple has been very strong in pushing for standards based drivers, by " "making drivers for the generic classes available in their operating system " "MacOS and discouraging the use of separate drivers for each new device. This " "chapter tries to collate essential information for a basic understanding of " "the USB 2.0 implementation stack in FreeBSD/NetBSD. It is recommended " "however to read it together with the relevant 2.0 specifications and other " "developer resources:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21784 msgid "" "USB 2.0 Specification (http://www.usb.org/developers/docs/usb20_docs/)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21788 msgid "" "Universal Host Controller Interface (UHCI) Specification " "(ftp://ftp.netbsd.org/pub/NetBSD/misc/blymn/uhci11d.pdf)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21793 msgid "" "Open Host Controller Interface (OHCI) Specification(ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.pdf)" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21798 msgid "" "Developer section of USB home page (http://www.usb.org/developers/)" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:21804 msgid "Structure of the USB Stack" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21806 msgid "" "The USB support in FreeBSD can be split into three layers. The lowest layer " "contains the host controller driver, providing a generic interface to the " "hardware and its scheduling facilities. It supports initialisation of the " "hardware, scheduling of transfers and handling of completed and/or failed " "transfers. Each host controller driver implements a virtual hub providing " "hardware independent access to the registers controlling the root ports on " "the back of the machine." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21816 msgid "" "The middle layer handles the device connection and disconnection, basic " "initialisation of the device, driver selection, the communication channels " "(pipes) and does resource management. This services layer also controls the " "default pipes and the device requests transferred over them." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21823 msgid "" "The top layer contains the individual drivers supporting specific (classes " "of) devices. These drivers implement the protocol that is used over the " "pipes other than the default pipe. They also implement additional " "functionality to make the device available to other parts of the kernel or " "userland. They use the USB driver interface (USBDI) exposed by the services " "layer." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:21834 msgid "Host Controllers" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:21836 msgid "USBhost controllers" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21838 msgid "" "The host controller (HC) controls the transmission of packets on the bus. " "Frames of 1 millisecond are used. At the start of each frame the host " "controller generates a Start of Frame (SOF) packet." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21843 msgid "" "The SOF packet is used to synchronise to the start of the frame and to keep " "track of the frame number. Within each frame packets are transferred, either " "from host to device (out) or from device to host (in). Transfers are always " "initiated by the host (polled transfers). Therefore there can only be one " "host per USB bus. Each transfer of a packet has a status stage in which the " "recipient of the data can return either ACK (acknowledge reception), NAK " "(retry), STALL (error condition) or nothing (garbled data stage, device not " "available or disconnected). Section 8.5 of the USB 2.0 Specification " "explains the details of packets in more detail. Four different types of " "transfers can occur on a USB bus: control, bulk, interrupt and isochronous. " "The types of transfers and their characteristics are described below." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21858 msgid "" "Large transfers between the device on the USB bus and the device driver are " "split up into multiple packets by the host controller or the HC driver." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:21862 msgid "" "Device requests (control transfers) to the default endpoints are special. " "They consist of two or three phases: SETUP, DATA (optional) and STATUS. The " "set-up packet is sent to the device. If there is a data phase, the direction " "of the data packet(s) is given in the set-up packet. The direction in the " "status phase is the opposite of the direction during the data phase, or IN " "if there was no data phase. The host controller hardware also provides " "registers with the current status of the root ports and the changes that " "have occurred since the last reset of the status change register. Access to " "these registers is provided through a virtualised hub as suggested in the " "USB specification. The virtual hub must comply with the hub device class " "given in chapter 11 of that specification. It must provide a default pipe " "through which device requests can be sent to it. It returns the standard " "andhub class specific set of descriptors. It should also provide an " "interrupt pipe that reports changes happening at its ports. There are " "currently two specifications for host controllers available: Universal Host " "Controller Interface (UHCI) from Intel and Open Host " "Controller Interface (OHCI) from Compaq, Microsoft, and " "National Semiconductor. The UHCI specification has been " "designed to reduce hardware complexity by requiring the host controller " "driver to supply a complete schedule of the transfers for each frame. OHCI " "type controllers are much more independent by providing a more abstract " "interface doing a lot of work themselves." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:21891 msgid "UHCI" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:21893 msgid "USB UHCI" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21898 msgid "" "The UHCI host controller maintains a framelist with 1024 pointers to per " "frame data structures. It understands two different data types: transfer " "descriptors (TD) and queue heads (QH). Each TD represents a packet to be " "communicated to or from a device endpoint. QHs are a means to groupTDs (and " "QHs) together." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21905 msgid "" "Each transfer consists of one or more packets. The UHCI driver splits large " "transfers into multiple packets. For every transfer, apart from isochronous " "transfers, a QH is allocated. For every type of transfer these QHs are " "collected at a QH for that type. Isochronous transfers have to be executed " "first because of the fixed latency requirement and are directly referred to " "by the pointer in the framelist. The last isochronous TD refers to the QH " "for interrupt transfers for that frame. All QHs for interrupt transfers " "point at the QH for control transfers, which in turn points at the QH for " "bulk transfers. The following diagram gives a graphical overview of this:" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21918 msgid "" "This results in the following schedule being run in each frame. After " "fetching the pointer for the current frame from the framelist the controller " "first executes the TDs for all the isochronous packets in that frame. The " "last of these TDs refers to the QH for the interrupt transfers for thatframe." " The host controller will then descend from that QH to the QHs for the " "individual interrupt transfers. After finishing that queue, the QH for the " "interrupt transfers will refer the controller to the QH for all control " "transfers. It will execute all the subqueues scheduled there, followed by " "all the transfers queued at the bulk QH. To facilitate the handling of " "finished or failed transfers different types of interrupts are generated by " "the hardware at the end of each frame. In the last TD for a transfer the " "Interrupt-On Completion bit is set by the HC driver to flag an interrupt " "when the transfer has completed. An error interrupt is flagged if a TD " "reaches its maximum error count. If the short packet detect bit is set in a " "TD and less than the set packet length is transferred this interrupt is " "flagged to notify the controller driver of the completed transfer. It is the " "host controller driver's task to find out which transfer has completed or " "produced an error. When called the interrupt service routine will locate all " "the finished transfers and call their callbacks." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21942 msgid "" "Refer to the UHCI Specification for a more elaborate " "description." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:21948 msgid "OHCI" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:21950 msgid "USB OHCI" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21955 msgid "" "Programming an OHCI host controller is much simpler. The controller assumes " "that a set of endpoints is available, and is aware of scheduling priorities " "and the ordering of the types of transfers in a frame. The main data " "structure used by the host controller is the endpoint descriptor (ED) to " "which a queue of transfer descriptors (TDs) is attached. The ED contains the " "maximum packet size allowed for an endpoint and the controller hardware does " "the splitting into packets. The pointers to the data buffers are updated " "after each transfer and when the start and end pointer are equal, the TD is " "retired to the done-queue. The four types of endpoints (interrupt, " "isochronous, control, and bulk) have their own queues. Control and bulk " "endpoints are queued each at their own queue. Interrupt EDs are queued in a " "tree, with the level in the tree defining the frequency at which they run." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21971 msgid "" "The schedule being run by the host controller in each frame looks as follows." " The controller will first run the non-periodic control and bulk queues, up " "to a time limit set by the HC driver. Then the interrupt transfers for that " "frame number are run, by using the lower five bits of the frame number as an " "index into level 0 of the tree of interrupts EDs. At the end of this tree " "the isochronous EDs are connected and these are traversed subsequently. The " "isochronous TDs contain the frame number of the first frame the transfer " "should be run in. After all the periodic transfers have been run, the " "control and bulk queues are traversed again. Periodically the interrupt " "service routine is called to process the done queue and call the callbacks " "for each transfer and reschedule interrupt and isochronous endpoints." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:21986 msgid "" "See the UHCI Specification for a more elaborate " "description. The middle layer provides access to the device in a controlled " "way and maintains resources in use by the different drivers and the services " "layer. The layer takes care of the following aspects:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21994 msgid "The device configuration information" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:21997 msgid "The pipes to communicate with a device" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22000 msgid "Probing and attaching and detaching form a device." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22008 msgid "USB Device Information" msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22011 msgid "Device Configuration Information" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22013 msgid "" "Each device provides different levels of configuration information. Each " "device has one or more configurations, of which one is selected during probe/" "attach. A configuration provides power and bandwidth requirements. Within " "each configuration there can be multiple interfaces. A device interface is a " "collection of endpoints. For example USB speakers can have an interface for " "the audio data (Audio Class) and an interface for the knobs, dials and " "buttons (HID Class). All interfaces in a configuration are active at the " "same time and can be attached to by different drivers. Each interface can " "have alternates, providing different quality of service parameters. In for " "example cameras this is used to provide different frame sizes and numbers of " "frames per second." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22028 msgid "" "Within each interface, 0 or more endpoints can be specified. Endpoints are " "the unidirectional access points for communicating with a device. They " "provide buffers to temporarily store incoming or outgoing data from the " "device. Each endpoint has a unique address within a configuration, the " "endpoint's number plus its direction. The default endpoint, endpoint 0, is " "not part of any interface and available in all configurations. It is managed " "by the services layer and not directly available to device drivers." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22044 msgid "" "This hierarchical configuration information is described in the device by a " "standard set of descriptors (see section 9.6 of the USB specification). They " "can be requested through the Get Descriptor Request. The services layer " "caches these descriptors to avoid unnecessary transfers on the USB bus. " "Access to the descriptors is provided through function calls." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22054 msgid "" "Device descriptors: General information about the device, like Vendor, " "Product and Revision Id, supported device class, subclass and protocol if " "applicable, maximum packet size for the default endpoint, etc." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22061 msgid "" "Configuration descriptors: The number of interfaces in this configuration, " "suspend and resume functionality supported and power requirements." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22067 msgid "" "Interface descriptors: interface class, subclass and protocol if applicable, " "number of alternate settings for the interface and the number of endpoints." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22073 msgid "" "Endpoint descriptors: Endpoint address, direction and type, maximum packet " "size supported and polling frequency if type is interrupt endpoint. There is " "no descriptor for the default endpoint (endpoint 0) and it is never counted " "in an interface descriptor." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22081 msgid "" "String descriptors: In the other descriptors string indices are supplied for " "some fields.These can be used to retrieve descriptive strings, possibly in " "multiple languages." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22088 msgid "" "Class specifications can add their own descriptor types that are available " "through the GetDescriptor Request." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22091 msgid "" "Pipes Communication to end points on a device flows through so-called pipes. " "Drivers submit transfers to endpoints to a pipe and provide a callback to be " "called on completion or failure of the transfer (asynchronous transfers) or " "wait for completion (synchronous transfer). Transfers to an endpoint are " "serialised in the pipe. A transfer can either complete, fail or time-out (if " "a time-out has been set). There are two types of time-outs for transfers. " "Time-outs can happen due to time-out on the USBbus (milliseconds). These " "time-outs are seen as failures and can be due to disconnection of the device." " A second form of time-out is implemented in software and is triggered when " "a transfer does not complete within a specified amount of time (seconds). " "These are caused by a device acknowledging negatively (NAK) the transferred " "packets. The cause for this is the device not being ready to receive data, " "buffer under- or overrun or protocol errors." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22109 msgid "" "If a transfer over a pipe is larger than the maximum packet size specified " "in the associated endpoint descriptor, the host controller (OHCI) or the HC " "driver (UHCI) will split the transfer into packets of maximum packet size, " "with the last packet possibly smaller than the maximum packet size." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22116 msgid "" "Sometimes it is not a problem for a device to return less data than " "requested. For example abulk-in-transfer to a modem might request 200 bytes " "of data, but the modem has only 5 bytes available at that time. The driver " "can set the short packet (SPD) flag. It allows the host controller to accept " "a packet even if the amount of data transferred is less than requested. This " "flag is only valid for in-transfers, as the amount of data to be sent to a " "device is always known beforehand. If an unrecoverable error occurs in a " "device during a transfer the pipe is stalled. Before any more data is " "accepted or sent the driver needs to resolve the cause of the stall and " "clear the endpoint stall condition through send the clear endpoint halt " "device request over the default pipe. The default endpoint should never " "stall." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22131 msgid "" "There are four different types of endpoints and corresponding pipes: - " "Control pipe / default pipe: There is one control pipe per device, connected " "to the default endpoint (endpoint 0). The pipe carries the device requests " "and associated data. The difference between transfers over the default pipe " "and other pipes is that the protocol for the transfers is described in the " "USB specification. These requests are used to reset and configure the device." " A basic set of commands that must be supported by each device is provided " "in chapter 9 of the USB specification. The commands supported on this pipe " "can be extended by a device class specification to support additional " "functionality." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22146 msgid "Bulk pipe: This is the USB equivalent to a raw transmission medium." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22151 msgid "" "Interrupt pipe: The host sends a request for data to the device and if the " "device has nothing to send, it will NAK the data packet. Interrupt transfers " "are scheduled at a frequency specified when creating the pipe." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22159 msgid "" "Isochronous pipe: These pipes are intended for isochronous data, for example " "video or audio streams, with fixed latency, but no guaranteed delivery. Some " "support for pipes of this type is available in the current implementation. " "Packets in control, bulk and interrupt transfers are retried if an error " "occurs during transmission or the device acknowledges the packet negatively " "(NAK) due to for example lack of buffer space to store the incoming data. " "Isochronous packets are however not retried in case of failed delivery or " "NAK of a packet as this might violate the timing constraints." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22174 msgid "" "The availability of the necessary bandwidth is calculated during the " "creation of the pipe. Transfers are scheduled within frames of 1 millisecond." " The bandwidth allocation within a frame is prescribed by the USB " "specification, section 5.6 [ 2]. Isochronous and interrupt transfers are " "allowed to consume up to 90% of the bandwidth within a frame. Packets for " "control and bulk transfers are scheduled after all isochronous and interrupt " "packets and will consume all the remaining bandwidth." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22184 msgid "" "More information on scheduling of transfers and bandwidth reclamation can be " "found in chapter 5 of the USB specification, section 1.3 of the UHCI " "specification, and section 3.4.2 of the OHCI specification." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22192 msgid "Device Probe and Attach" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:22194 msgid "USB probe" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22199 msgid "" "After the notification by the hub that a new device has been connected, the " "service layer switches on the port, providing the device with 100 mA of " "current. At this point the device is in its default state and listening to " "device address 0. The services layer will proceed to retrieve the various " "descriptors through the default pipe. After that it will send a Set Address " "request to move the device away from the default device address (address 0). " "Multiple device drivers might be able to support the device. For example a " "modem driver might be able to support an ISDN TA through the AT " "compatibility interface. A driver for that specific model of the ISDN " "adapter might however be able to provide much better support for this device." " To support this flexibility, the probes return priorities indicating their " "level of support. Support for a specific revision of a product ranks the " "highest and the generic driver the lowest priority. It might also be that " "multiple drivers could attach to one device if there are multiple interfaces " "within one configuration. Each driver only needs to support a subset of the " "interfaces." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22218 msgid "" "The probing for a driver for a newly attached device checks first for device " "specific drivers. If not found, the probe code iterates over all supported " "configurations until a driver attaches in a configuration. To support " "devices with multiple drivers on different interfaces, the probe iterates " "over all interfaces in a configuration that have not yet been claimed by a " "driver. Configurations that exceed the power budget for the hub are ignored. " "During attach the driver should initialise the device to its proper state, " "but not reset it, as this will make the device disconnect itself from the " "bus and restart the probing process for it. To avoid consuming unnecessary " "bandwidth should not claim the interrupt pipe at attach time, but should " "postpone allocating the pipe until the file is opened and the data is " "actually used. When the file is closed the pipe should be closed again, even " "though the device might still be attached." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22236 msgid "Device Disconnect and Detach" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:22238 msgid "USB disconnect" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22243 msgid "" "A device driver should expect to receive errors during any transaction with " "the device. The design of USB supports and encourages the disconnection of " "devices at any point in time. Drivers should make sure that they do the " "right thing when the device disappears." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22249 msgid "" "Furthermore a device that has been disconnected and reconnected will not be " "reattached at the same device instance. This might change in the future when " "more devices support serial numbers (see the device descriptor) or other " "means of defining an identity for a device have been developed." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22256 msgid "" "The disconnection of a device is signaled by a hub in the interrupt packet " "delivered to the hub driver. The status change information indicates which " "port has seen a connection change. The device detach method for all device " "drivers for the device connected on that port are called and the structures " "cleaned up. If the port status indicates that in the mean time a device has " "been connected to that port, the procedure for probing and attaching the " "device will be started. A device reset will produce a disconnect-connect " "sequence on the hub and will be handled as described above." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22271 msgid "USB Drivers Protocol Information" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22273 msgid "" "The protocol used over pipes other than the default pipe is undefined by the " "USB specification. Information on this can be found from various sources. " "The most accurate source is the developer's section on the USB home pages. " "From these pages, a growing number of deviceclass specifications are " "available. These specifications specify what a compliant device should look " "like from a driver perspective, basic functionality it needs to provide and " "the protocol that is to be used over the communication channels. The USB " "specification includes the description of the Hub Class. A class " "specification for Human Interface Devices (HID) has been created to cater " "for keyboards, tablets, bar-code readers, buttons, knobs, switches, etc. A " "third example is the class specification for mass storage devices. For a " "full list of device classes see the developers section on the USB home pages." "" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22289 msgid "" "For many devices the protocol information has not yet been published however." " Information on the protocol being used might be available from the company " "making the device. Some companies will require you to sign a Non -Disclosure " "Agreement (NDA) before giving you the specifications. This in most cases " "precludes making the driver open source." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22296 msgid "" "Another good source of information is the Linux driver sources, as a number " "of companies have started to provide drivers for Linux for their devices. It " "is always a good idea to contact the authors of those drivers for their " "source of information." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22302 msgid "" "Example: Human Interface Devices The specification for the Human Interface " "Devices like keyboards, mice, tablets, buttons, dials,etc. is referred to in " "other device class specifications and is used in many devices." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22307 msgid "" "For example audio speakers provide endpoints to the digital to analogue " "converters and possibly an extra pipe for a microphone. They also provide a " "HID endpoint in a separate interface for the buttons and dials on the front " "of the device. The same is true for the monitor control class. It is " "straightforward to build support for these interfaces through the available " "kernel and userland libraries together with the HID class driver or the " "generic driver. Another device that serves as an example for interfaces " "within one configuration driven by different device drivers is a cheap " "keyboard with built-in legacy mouse port. To avoid having the cost of " "including the hardware for a USB hub in the device, manufacturers combined " "the mouse data received from the PS/2 port on the back of the keyboard and " "the key presses from the keyboard into two separate interfaces in the same " "configuration. The mouse and keyboard drivers each attach to the appropriate " "interface and allocate the pipes to the two independent endpoints." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:22326 msgid "USB firmware" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22331 msgid "" "Example: Firmware download Many devices that have been developed are based " "on a general purpose processor with an additional USB core added to it. " "Because the development of drivers and firmware for USB devices is still " "very new, many devices require the downloading of the firmware after they " "have been connected." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22338 msgid "" "The procedure followed is straightforward. The device identifies itself " "through a vendor and product Id. The first driver probes and attaches to it " "and downloads the firmware into it. After that the device soft resets itself " "and the driver is detached. After a short pause the device announces its " "presence on the bus. The device will have changed its vendor/product/" "revision Id to reflect the fact that it has been supplied with firmware and " "as a consequence a second driver will probe it and attach to it." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22348 msgid "" "An example of these types of devices is the ActiveWire I/O board, based on " "the EZ-USB chip. For this chip a generic firmware downloader is available. " "The firmware downloaded into the ActiveWire board changes the revision Id. " "It will then perform a soft reset of the USB part of the EZ-USB chip to " "disconnect from the USB bus and again reconnect." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22355 msgid "" "Example: Mass Storage Devices Support for mass storage devices is mainly " "built around existing protocols. The Iomega USB Zipdrive is based on the " "SCSI version of their drive. The SCSI commands and status messages are " "wrapped in blocks and transferred over the bulk pipes to and from the " "device, emulating a SCSI controller over the USB wire. ATAPI and UFI " "commands are supported in a similar fashion." msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:22363 msgid "ATAPI" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22365 msgid "" "The Mass Storage Specification supports 2 different types of wrapping of the " "command block.The initial attempt was based on sending the command and " "status through the default pipe and using bulk transfers for the data to be " "moved between the host and the device. Based on experience a second approach " "was designed that was based on wrapping the command and status blocks and " "sending them over the bulk out and in endpoint. The specification specifies " "exactly what has to happen when and what has to be done in case an error " "condition is encountered. The biggest challenge when writing drivers for " "these devices is to fit USB based protocol into the existing support for " "mass storage devices. CAM provides hooks to do this in a fairly straight " "forward way. ATAPI is less simple as historically the IDE interface has " "never had many different appearances." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22380 msgid "" "The support for the USB floppy from Y-E Data is again less straightforward " "as a new command set has been designed." msgstr "" #. (itstool) path: info/title #: book.translate.xml:22411 msgid "Newbus" msgstr "" #. (itstool) path: affiliation/address #: book.translate.xml:22420 #, no-wrap msgid "\n" " asmodai@FreeBSD.org\n" " " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:22414 msgid "" " Jeroen Ruigrok van der Werven " "(asmodai) <_:address-1/> Written by " msgstr "" #. (itstool) path: affiliation/address #: book.translate.xml:22432 #, no-wrap msgid "\n" " hiten@uk.FreeBSD.org\n" " " msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:22426 msgid "" " Hiten Pandya <_:address-1/> " msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:22440 msgid "" "Special thanks to Matthew N. Dodd, Warner Losh, Bill Paul, Doug " "Rabson, Mike Smith, Peter Wemm and Scott Long." msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:22444 msgid "This chapter explains the Newbus device framework in detail." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22451 msgid "Purpose of a Device Driver" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:22455 msgid "device driverintroduction" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22458 msgid "" "A device driver is a software component which provides the interface between " "the kernel's generic view of a peripheral (e.g., disk, network adapter) and " "the actual implementation of the peripheral. The device driver " "interface (DDI) is the defined interface between the kernel and " "the device driver component." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22467 msgid "Types of Device Drivers" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22469 msgid "" "There used to be days in UNIX, " "and thus FreeBSD, in which there were four types of devices defined:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22473 msgid "block device drivers" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22474 msgid "character device drivers" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22475 msgid "network device drivers" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22476 msgid "pseudo-device drivers" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22481 msgid "" "Block devices performed in a way that used fixed size " "blocks [of data]. This type of driver depended on the so-called " "buffer cache, which had cached accessed blocks of data " "in a dedicated part of memory. Often this buffer cache was based on write-" "behind, which meant that when data was modified in memory it got synced to " "disk whenever the system did its periodical disk flushing, thus optimizing " "writes." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22496 msgid "" "However, in the versions of FreeBSD 4.0 and onward the distinction between " "block and character devices became non-existent." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22507 msgid "Overview of Newbus" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22511 msgid "" "Newbus is the implementation of a new bus architecture " "based on abstraction layers which saw its introduction in FreeBSD 3.0 when " "the Alpha port was imported into the source tree. It was not until 4.0 " "before it became the default system to use for device drivers. Its goals are " "to provide a more object-oriented means of interconnecting the various " "busses and devices which a host system provides to the Operating " "System." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22520 msgid "Its main features include amongst others:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22523 msgid "dynamic attaching" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22524 msgid "easy modularization of drivers" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22525 msgid "pseudo-busses" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22528 msgid "" "One of the most prominent changes is the migration from the flat and ad-hoc " "system to a device tree layout." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22531 msgid "" "At the top level resides the root device " "which is the parent to hang all other devices on. For each architecture, " "there is typically a single child of root which has such " "things as host-to-PCI bridges, etc. attached to it. For " "x86, this root device is the nexus device. For Alpha, various different models of Alpha have " "different top-level devices corresponding to the different hardware " "chipsets, including lca, apecs, " "cia and tsunami." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22544 msgid "" "A device in the Newbus context represents a single hardware entity in the " "system. For instance each PCI device is represented by a Newbus device. Any " "device in the system can have children; a device which has children is often " "called a bus. Examples of common busses " "in the system are ISA and PCI, which manage lists of devices attached to ISA " "and PCI busses respectively." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22552 msgid "" "Often, a connection between different kinds of bus is represented by a " "bridge device, which normally has one " "child for the attached bus. An example of this is a PCI-to-PCI " "bridge which is represented by a device " "pcibN on the parent PCI bus and " "has a child pciN for the attached " "bus. This layout simplifies the implementation of the PCI bus tree, allowing " "common code to be used for both top-level and bridged busses." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22564 msgid "" "Each device in the Newbus architecture asks its parent to map its resources. " "The parent then asks its own parent until the nexus is reached. So, " "basically the nexus is the only part of the Newbus system which knows about " "all resources." msgstr "" #. (itstool) path: tip/para #: book.translate.xml:22569 msgid "" "An ISA device might want to map its IO port at 0x230, so " "it asks its parent, in this case the ISA bus. The ISA bus hands it over to " "the PCI-to-ISA bridge which in its turn asks the PCI bus, which reaches the " "host-to-PCI bridge and finally the nexus. The beauty of this transition " "upwards is that there is room to translate the requests. For example, the " "0x230 IO port request might become memory-mapped at " "0xb0000230 on a MIPS box by the PCI " "bridge." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22580 msgid "" "Resource allocation can be controlled at any place in the device tree. For " "instance on many Alpha platforms, ISA interrupts are managed separately from " "PCI interrupts and resource allocations for ISA interrupts are managed by " "the Alpha's ISA bus device. On IA-32, ISA and PCI interrupts are both " "managed by the top-level nexus device. For both ports, memory and port " "address space is managed by a single entity - nexus for IA-32 and the " "relevant chipset driver on Alpha (e.g., CIA or tsunami)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22590 msgid "" "In order to normalize access to memory and port mapped resources, Newbus " "integrates the bus_space APIs from NetBSD. These provide " "a single API to replace inb/outb and direct memory reads/writes. The " "advantage of this is that a single driver can easily use either memory-" "mapped registers or port-mapped registers (some hardware supports both)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22597 msgid "" "This support is integrated into the resource allocation mechanism. When a " "resource is allocated, a driver can retrieve the associated bus_space_tag_t and bus_space_handle_t from the resource." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22602 msgid "" "Newbus also allows for definitions of interface methods in files dedicated " "to this purpose. These are the .m files that are found " "under the src/sys hierarchy." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22607 msgid "" "The core of the Newbus system is an extensible object-based " "programming model. Each device in the system has a table of methods " "which it supports. The system and other devices uses those methods to " "control the device and request services. The different methods supported by " "a device are defined by a number of interfaces. An " "interface is simply a group of related methods which can be " "implemented by a device." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22616 msgid "" "In the Newbus system, the methods for a device are provided by the various " "device drivers in the system. When a device is attached to a driver during " "auto-configuration, it uses the method table declared " "by the driver. A device can later detach from its " "driver and re-attach to a new driver with a new method " "table. This allows dynamic replacement of drivers which can be useful for " "driver development." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22626 msgid "" "The interfaces are described by an interface definition language similar to " "the language used to define vnode operations for file systems. The interface " "would be stored in a methods file (which would normally be named " "foo_if.m)." msgstr "" #. (itstool) path: example/title #: book.translate.xml:22633 msgid "Newbus Methods" msgstr "" #. (itstool) path: example/programlisting #: book.translate.xml:22635 #, no-wrap msgid "" " # Foo subsystem/driver (a comment...)\n" "\n" " INTERFACE foo\n" "\n" " METHOD int doit {\n" " device_t dev;\n" " };\n" "\n" " # DEFAULT is the method that will be used, if a method was not\n" " # provided via: DEVMETHOD()\n" "\n" " METHOD void doit_to_child {\n" " device_t dev;\n" " driver_t child;\n" " } DEFAULT doit_generic_to_child;" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22652 msgid "" "When this interface is compiled, it generates a header file " "foo_if.h which contains function " "declarations:" msgstr "" #. (itstool) path: sect1/programlisting #: book.translate.xml:22656 #, no-wrap msgid "" " int FOO_DOIT(device_t dev);\n" " int FOO_DOIT_TO_CHILD(device_t dev, device_t child);" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22659 msgid "" "A source file, foo_if.c is also created " "to accompany the automatically generated header file; it contains " "implementations of those functions which look up the location of the " "relevant functions in the object's method table and call that function." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22665 msgid "" "The system defines two main interfaces. The first fundamental interface is " "called device and includes methods which " "are relevant to all devices. Methods in the device interface include probe, " "attach and detach to control detection of hardware and " "shutdown, suspend and resume for " "critical event notification." msgstr "" #. (itstool) path: footnote/para #: book.translate.xml:22682 msgid "" "bus_generic_read_ivar9 and " "bus_generic_write_ivar9" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22678 msgid "" "The second, more complex interface is bus. This interface contains methods suitable for devices which have " "children, including methods to access bus specific per-device information <_:" "footnote-1/>, event notification (child_detached, driver_added) " "and resource management (alloc_resource, activate_resource, " "deactivate_resource, " "release_resource)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22693 msgid "" "Many methods in the bus interface are performing services for " "some child of the bus device. These methods would normally use the first two " "arguments to specify the bus providing the service and the child device " "which is requesting the service. To simplify driver code, many of these " "methods have accessor functions which lookup the parent and call a method on " "the parent. For instance the method BUS_TEARDOWN_INTR(device_t dev, " "device_t child, ...) can be called using the function " "bus_teardown_intr(device_t child, ...)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22705 msgid "" "Some bus types in the system define additional interfaces to provide access " "to bus-specific functionality. For instance, the PCI bus driver defines the " "pci interface which has two methods " "read_config and " "write_config for accessing the " "configuration registers of a PCI device." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22715 msgid "Newbus API" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22717 msgid "" "As the Newbus API is huge, this section makes some effort at documenting it. " "More information to come in the next revision of this document." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22722 msgid "Important Locations in the Source Hierarchy" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22724 msgid "" "src/sys/[arch]/[arch] - Kernel code for a specific " "machine architecture resides in this directory. For example, the " "i386 architecture, or the SPARC64 " "architecture." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22729 msgid "" "src/sys/dev/[bus] - device support for a specific " "[bus] resides in this directory." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22733 msgid "" "src/sys/dev/pci - PCI bus support code resides in this " "directory." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22736 msgid "" "src/sys/[isa|pci] - PCI/ISA device drivers reside in " "this directory. The PCI/ISA bus support code used to exist in this directory " "in FreeBSD version 4.0." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:22743 msgid "Important Structures and Type Definitions" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22745 msgid "" "devclass_t - This is a type definition of a pointer to a " "struct devclass." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22748 msgid "" "device_method_t - This is the same as " "kobj_method_t (see src/sys/kobj.h)." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22752 msgid "" "device_t - This is a type definition of a pointer to a " "struct device. device_t represents a " "device in the system. It is a kernel object. See src/sys/sys/" "bus_private.h for implementation details." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22759 msgid "" "driver_t - This is a type definition which references " "struct driver. The driver struct is a " "class of the device kernel object; it also holds data " "private to the driver." msgstr "" #. (itstool) path: figure/title #: book.translate.xml:22766 msgid "driver_t Implementation" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:22768 #, no-wrap msgid "" " struct driver {\n" " KOBJ_CLASS_FIELDS;\n" " void *priv; /* driver private data */\n" " };" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:22774 msgid "" "A device_state_t type, which is an enumeration, " "device_state. It contains the possible states of a Newbus " "device before and after the autoconfiguration process." msgstr "" #. (itstool) path: figure/title #: book.translate.xml:22780 msgid "Device States device_state_t" msgstr "" #. (itstool) path: figure/programlisting #: book.translate.xml:22783 #, no-wrap msgid "" " /*\n" " * src/sys/sys/bus.h\n" " */\n" " typedef enum device_state {\n" " DS_NOTPRESENT, /* not probed or probe failed */\n" " DS_ALIVE, /* probe succeeded */\n" " DS_ATTACHED, /* attach method called */\n" " DS_BUSY /* device is open */\n" " } device_state_t;" msgstr "" #. (itstool) path: info/title #: book.translate.xml:22805 msgid "Sound Subsystem" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:22807 msgid "" "Jean-FrancoisDockesContributed by " msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:22817 msgid "sound subsystem" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22819 msgid "" "The FreeBSD sound subsystem cleanly separates generic sound handling issues " "from device-specific ones. This makes it easier to add support for new " "hardware." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22823 msgid "" "The pcm4 framework is the central piece of the sound " "subsystem. It mainly implements the following elements:" msgstr "" #. (itstool) path: sect1/indexterm #: book.translate.xml:22826 msgid "system call interface" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22830 msgid "" "A system call interface (read, write, ioctls) to digitized sound and mixer " "functions. The ioctl command set is compatible with the legacy " "OSS or Voxware interface, allowing " "common multimedia applications to be ported without modification." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22839 msgid "" "Common code for processing sound data (format conversions, virtual channels)." "" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22844 msgid "" "A uniform software interface to hardware-specific audio interface modules." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22849 msgid "" "Additional support for some common hardware interfaces (ac97), or shared " "hardware-specific code (ex: ISA DMA routines)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22855 msgid "" "The support for specific sound cards is implemented by hardware-specific " "drivers, which provide channel and mixer interfaces to plug into the generic " "pcm code." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22860 msgid "" "In this chapter, the term pcm will refer to the " "central, common part of the sound driver, as opposed to the hardware-" "specific modules." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22864 msgid "" "The prospective driver writer will of course want to start from an existing " "module and use the code as the ultimate reference. But, while the sound code " "is nice and clean, it is also mostly devoid of comments. This document tries " "to give an overview of the framework interface and answer some questions " "that may arise while adapting the existing code." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22871 msgid "" "As an alternative, or in addition to starting from a working example, you " "can find a commented driver template at https://people.FreeBSD.org/~cg/template.c" msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22878 msgid "Files" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22880 msgid "" "All the relevant code lives in /usr/src/sys/dev/sound/, " "except for the public ioctl interface definitions, found in /usr/" "src/sys/sys/soundcard.h" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22885 msgid "" "Under /usr/src/sys/dev/sound/, the pcm/ directory holds the central code, while the pci/, isa/ and usb/ " "directories have the drivers for PCI and ISA boards, and for USB audio " "devices." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22893 msgid "Probing, Attaching, etc." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22895 msgid "" "Sound drivers probe and attach in almost the same way as any hardware driver " "module. You might want to look at the ISA or PCI specific sections of the handbook " "for more information." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22899 msgid "However, sound drivers differ in some ways:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22903 msgid "" "They declare themselves as pcm class devices, with a " "struct snddev_info device private " "structure:" msgstr "" #. (itstool) path: listitem/programlisting #: book.translate.xml:22908 #, no-wrap msgid "" " static driver_t xxx_driver = {\n" " \"pcm\",\n" " xxx_methods,\n" " sizeof(struct snddev_info)\n" " };\n" "\n" " DRIVER_MODULE(snd_xxxpci, pci, xxx_driver, pcm_devclass, 0, 0);\n" " MODULE_DEPEND(snd_xxxpci, snd_pcm, PCM_MINVER, " "PCM_PREFVER,PCM_MAXVER);" msgstr "" #. (itstool) path: para/indexterm #: book.translate.xml:22917 msgid "device driverssound" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22917 msgid "" "Most sound drivers<_:indexterm-1/> need to store additional private " "information about their device. A private data structure is usually " "allocated in the attach routine. Its address is passed to pcm by the calls to pcm_register() and " "mixer_init(). pcm later passes " "back this address as a parameter in calls to the sound driver interfaces." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22931 msgid "" "The sound driver attach routine should declare its MIXER or AC97 interface " "to pcm by calling mixer_init(). " "For a MIXER interface, this causes in turn a call to xxxmixer_init()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22938 msgid "" "The sound driver attach routine declares its general CHANNEL configuration " "to pcm by calling pcm_register(dev, sc, " "nplay, nrec), where sc is the address for the " "device data structure, used in further calls from pcm, " "and nplay and nrec are the number of " "play and record channels." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22949 msgid "" "The sound driver attach routine declares each of its channel objects by " "calls to pcm_addchan(). This sets up the channel glue " "in pcm and causes in turn a call to xxxchannel_init()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22959 msgid "" "The sound driver detach routine should call pcm_unregister() before releasing its resources." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22965 msgid "There are two possible methods to handle non-PnP devices:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22970 msgid "" "Use a device_identify() method (example: " "sound/isa/es1888.c). The device_identify() method probes for the hardware at known addresses and, if it finds " "a supported device, creates a new pcm device which is then passed to probe/" "attach." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:22979 msgid "" "Use a custom kernel configuration with appropriate hints for pcm devices " "(example: sound/isa/mss.c)." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22985 msgid "" "pcm drivers should implement device_suspend, device_resume and device_shutdown routines, so that power management and module unloading function " "correctly." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:22993 msgid "Interfaces" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22995 msgid "" "The interface between the pcm core and the sound " "drivers is defined in terms of kernel " "objects." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:22998 msgid "" "There are two main interfaces that a sound driver will usually provide: " "CHANNEL and either MIXER or " "AC97." msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:23002 msgid "" "The AC97 interface is a very small hardware access " "(register read/write) interface, implemented by drivers for hardware with an " "AC97 codec. In this case, the actual MIXER interface is provided by the " "shared AC97 code in pcm." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23009 msgid "The CHANNEL Interface" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23012 msgid "Common Notes for Function Parameters" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23014 msgid "" "Sound drivers usually have a private data structure to describe their " "device, and one structure for each play and record data channel that it " "supports." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23018 msgid "" "For all CHANNEL interface functions, the first parameter is an opaque " "pointer." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23021 msgid "" "The second parameter is a pointer to the private channel data structure, " "except for channel_init() which has a pointer to the " "private device structure (and returns the channel pointer for further use by " "pcm)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23030 msgid "Overview of Data Transfer Operations" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23032 msgid "" "For sound data transfers, the pcm core and the sound " "drivers communicate through a shared memory area, described by a struct snd_dbuf." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23037 msgid "" "struct snd_dbuf is private to " "pcm, and sound drivers obtain values of interest by " "calls to accessor functions (sndbuf_getxxx())." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23042 msgid "" "The shared memory area has a size of sndbuf_getsize() " "and is divided into fixed size blocks of sndbuf_getblksz() bytes." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23047 msgid "" "When playing, the general transfer mechanism is as follows (reverse the idea " "for recording):" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23052 msgid "" "pcm initially fills up the buffer, then calls the sound " "driver's xxxchannel_trigger() function with a parameter of PCMTRIG_START." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23059 msgid "" "The sound driver then arranges to repeatedly transfer the whole memory area " "(sndbuf_getbuf(), sndbuf_getsize()) to the device, in blocks of sndbuf_getblksz() bytes. It calls back the chn_intr() " "pcm function for each transferred block (this will " "typically happen at interrupt time)." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23071 msgid "" "chn_intr() arranges to copy new data to the area that " "was transferred to the device (now free), and make appropriate updates to " "the snd_dbuf structure." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23080 msgid "channel_init" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23082 msgid "" "xxxchannel_init() is called to initialize each of the " "play or record channels. The calls are initiated from the sound driver " "attach routine. (See the probe and " "attach section)." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23088 #, no-wrap msgid "" " static void *\n" " xxxchannel_init(kobj_t obj, void *data,\n" " struct snd_dbuf *b, struct pcm_channel *c, int dir)\n" " {\n" " struct xxx_info *sc = data;\n" " struct xxx_chinfo *ch;\n" " ...\n" " return ch;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23100 msgid "" "b is the address for the channel struct snd_dbuf. It should be initialized in the " "function by calling sndbuf_alloc(). The buffer size to " "use is normally a small multiple of the 'typical' unit transfer size for " "your device." msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23107 msgid "" "c is the pcm channel control " "structure pointer. This is an opaque object. The function should store it in " "the local channel structure, to be used in later calls to pcm (ie: chn_intr(c))." msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23114 msgid "" "dir indicates the channel direction " "(PCMDIR_PLAY or PCMDIR_REC)." msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23120 msgid "" "The function should return a pointer to the private area used to control " "this channel. This will be passed as a parameter to other channel interface " "calls." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23128 msgid "channel_setformat" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23130 msgid "" "xxxchannel_setformat() should set up the hardware for " "the specified channel for the specified sound format." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23134 #, no-wrap msgid "" " static int\n" " xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format)\n" " {\n" " struct xxx_chinfo *ch = data;\n" " ...\n" " return 0;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23144 msgid "" "format is specified as an AFMT_XXX value (soundcard.h)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23152 msgid "channel_setspeed" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23154 msgid "" "xxxchannel_setspeed() sets up the channel hardware for " "the specified sampling speed, and returns the possibly adjusted speed." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23158 #, no-wrap msgid "" " static int\n" " xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed)\n" " {\n" " struct xxx_chinfo *ch = data;\n" " ...\n" " return speed;\n" " }" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23168 msgid "channel_setblocksize" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23170 msgid "" "xxxchannel_setblocksize() sets the block size, which is " "the size of unit transactions between pcm and the sound " "driver, and between the sound driver and the device. Typically, this would " "be the number of bytes transferred before an interrupt occurs. During a " "transfer, the sound driver should call pcm's " "chn_intr() every time this size has been transferred." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23180 msgid "" "Most sound drivers only take note of the block size here, to be used when an " "actual transfer will be started." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23184 #, no-wrap msgid "" " static int\n" " xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t " "blocksize)\n" " {\n" " struct xxx_chinfo *ch = data;\n" " ...\n" " return blocksize;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23194 msgid "" "The function returns the possibly adjusted block size. In case the block " "size is indeed changed, sndbuf_resize() should be " "called to adjust the buffer." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23203 msgid "channel_trigger" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23205 msgid "" "xxxchannel_trigger() is called by pcm to control data transfer operations in the driver." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23209 #, no-wrap msgid "" " static int\n" " xxxchannel_trigger(kobj_t obj, void *data, int go)\n" " {\n" " struct xxx_chinfo *ch = data;\n" " ...\n" " return 0;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23219 msgid "" "go defines the action for the current call. The possible " "values are:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23224 msgid "" "PCMTRIG_START: the driver should start a data transfer " "from or to the channel buffer. If needed, the buffer base and size can be " "retrieved through sndbuf_getbuf() and " "sndbuf_getsize()." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23233 msgid "" "PCMTRIG_EMLDMAWR / PCMTRIG_EMLDMARD: " "this tells the driver that the input or output buffer may have been updated. " "Most drivers just ignore these calls." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23241 msgid "" "PCMTRIG_STOP / PCMTRIG_ABORT: the " "driver should stop the current transfer." msgstr "" #. (itstool) path: note/para #: book.translate.xml:23250 msgid "" "If the driver uses ISA DMA, sndbuf_isadma() should be " "called before performing actions on the device, and will take care of the " "DMA chip side of things." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23258 msgid "channel_getptr" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23260 msgid "" "xxxchannel_getptr() returns the current offset in the " "transfer buffer. This will typically be called by chn_intr(), and this is how pcm knows where it can " "transfer new data." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23268 msgid "channel_free" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23270 msgid "" "xxxchannel_free() is called to free up channel " "resources, for example when the driver is unloaded, and should be " "implemented if the channel data structures are dynamically allocated or if " "sndbuf_alloc() was not used for buffer allocation." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23279 msgid "channel_getcaps" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23281 #, no-wrap msgid "" " struct pcmchan_caps *\n" " xxxchannel_getcaps(kobj_t obj, void *data)\n" " {\n" " return &xxx_caps;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23290 msgid "" "The routine returns a pointer to a (usually statically-defined) pcmchan_caps structure (defined in " "sound/pcm/channel.h. The structure holds the minimum " "and maximum sampling frequencies, and the accepted sound formats. Look at " "any sound driver for an example." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23302 msgid "More Functions" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23304 msgid "" "channel_reset(), channel_resetdone(), and channel_notify() are for special " "purposes and should not be implemented in a driver without discussing it on " "the FreeBSD multimedia mailing list." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23310 msgid "channel_setdir() is deprecated." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23316 msgid "The MIXER Interface" msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23319 msgid "mixer_init" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23321 msgid "" "xxxmixer_init() initializes the hardware and tells " "pcm what mixer devices are available for playing and " "recording" msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23325 #, no-wrap msgid "" " static int\n" " xxxmixer_init(struct snd_mixer *m)\n" " {\n" " struct xxx_info *sc = mix_getdevinfo(m);\n" " u_int32_t v;\n" "\n" " [Initialize hardware]\n" "\n" " [Set appropriate bits in v for play mixers]\n" " mix_setdevs(m, v);\n" " [Set appropriate bits in v for record mixers]\n" " mix_setrecdevs(m, v)\n" "\n" " return 0;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23343 msgid "" "Set bits in an integer value and call mix_setdevs() and " "mix_setrecdevs() to tell pcm what " "devices exist." msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23350 msgid "" "Mixer bits definitions can be found in soundcard.h " "(SOUND_MASK_XXX values and SOUND_MIXER_XXX bit shifts)." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23357 msgid "mixer_set" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23359 msgid "" "xxxmixer_set() sets the volume level for one mixer " "device." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23362 #, no-wrap msgid "" " static int\n" " xxxmixer_set(struct snd_mixer *m, unsigned dev,\n" " unsigned left, unsigned right)\n" " {\n" " struct sc_info *sc = mix_getdevinfo(m);\n" " [set volume level]\n" " return left | (right << 8);\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23373 msgid "The device is specified as a SOUND_MIXER_XXX value" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23376 msgid "" "The volume values are specified in range [0-100]. A value of zero should " "mute the device." msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23381 msgid "" "As the hardware levels probably will not match the input scale, and some " "rounding will occur, the routine returns the actual level values (in range 0-" "100) as shown." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23391 msgid "mixer_setrecsrc" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23393 msgid "" "xxxmixer_setrecsrc() sets the recording source device." msgstr "" #. (itstool) path: sect3/programlisting #: book.translate.xml:23396 #, no-wrap msgid "" " static int\n" " xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)\n" " {\n" " struct xxx_info *sc = mix_getdevinfo(m);\n" "\n" " [look for non zero bit(s) in src, set up hardware]\n" "\n" " [update src to reflect actual action]\n" " return src;\n" " }" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23409 msgid "The desired recording devices are specified as a bit field" msgstr "" #. (itstool) path: callout/para #: book.translate.xml:23414 msgid "" "The actual devices set for recording are returned. Some drivers can only set " "one device for recording. The function should return -1 if an error occurs." msgstr "" #. (itstool) path: sect3/title #: book.translate.xml:23422 msgid "mixer_uninit, mixer_reinit" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23424 msgid "" "xxxmixer_uninit() should ensure that all sound is muted " "and if possible mixer hardware should be powered down" msgstr "" #. (itstool) path: sect3/para #: book.translate.xml:23428 msgid "" "xxxmixer_reinit() should ensure that the mixer hardware " "is powered up and any settings not controlled by mixer_set() or mixer_setrecsrc() are restored." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23436 msgid "The AC97 Interface" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23438 msgid "AC97" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23440 msgid "" "The AC97 interface is implemented by drivers with an " "AC97 codec. It only has three methods:" msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23446 msgid "" "xxxac97_init() returns the number of ac97 codecs found." msgstr "" #. (itstool) path: listitem/para #: book.translate.xml:23451 msgid "" "ac97_read() and ac97_write() read " "or write a specified register." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23457 msgid "" "The AC97 interface is used by the AC97 code in " "pcm to perform higher level operations. Look at " "sound/pci/maestro3.c or many others under " "sound/pci/ for an example." msgstr "" #. (itstool) path: chapter/title #: book.translate.xml:23473 msgid "PC Card" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:23475 msgid "PC Card" msgstr "" #. (itstool) path: chapter/indexterm #: book.translate.xml:23476 msgid "CardBus" msgstr "" #. (itstool) path: chapter/para #: book.translate.xml:23478 msgid "" "This chapter will talk about the FreeBSD mechanisms for writing a device " "driver for a PC Card or CardBus device. However, at present it just " "documents how to add a new device to an existing pccard driver." msgstr "" #. (itstool) path: sect1/title #: book.translate.xml:23484 msgid "Adding a Device" msgstr "" #. (itstool) path: sect1/para #: book.translate.xml:23486 msgid "" "Device drivers know what devices they support. There is a table of supported " "devices in the kernel that drivers use to attach to a device." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23493 msgid "CIS" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23494 msgid "" "PC Cards are identified in one of two ways, both based on the " "Card Information Structure (CIS) stored on the card. The first method " "is to use numeric manufacturer and product numbers. The second method is to " "use the human readable strings that are also contained in the CIS. The PC " "Card bus uses a centralized database and some macros to facilitate a design " "pattern to help the driver writer match devices to his driver." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23505 msgid "" "Original equipment manufacturers (OEMs) often develop a " "reference design for a PC Card product, then sell this design to other " "companies to market. Those companies refine the design, market the product " "to their target audience or geographic area, and put their own name plate " "onto the card. The refinements to the physical card are typically very " "minor, if any changes are made at all. To strengthen their brand, these " "vendors place their company name in the human readable strings in the CIS " "space, but leave the manufacturer and product IDs unchanged." msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23516 msgid "NetGear" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23517 msgid "Linksys" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23518 msgid "D-Link" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23520 msgid "" "Because of this practice, FreeBSD drivers usually rely on numeric IDs for " "device identification. Using numeric IDs and a centralized database " "complicates adding IDs and support for cards to the system. One must " "carefully check to see who really made the card, especially when it appears " "that the vendor who made the card might already have a different " "manufacturer ID listed in the central database. Linksys, D-Link, and NetGear " "are a number of US manufacturers of LAN hardware that often sell the same " "design. These same designs can be sold in Japan under names such as Buffalo " "and Corega. Often, these devices will all have the same manufacturer and " "product IDs." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23533 msgid "" "The PC Card bus code keeps a central database of card information, but not " "which driver is associated with them, in /sys/dev/pccard/" "pccarddevs. It also provides a set of macros that allow one to " "easily construct simple entries in the table the driver uses to claim " "devices." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23540 msgid "" "Finally, some really low end devices do not contain manufacturer " "identification at all. These devices must be detected by matching the human " "readable CIS strings. While it would be nice if we did not need this method " "as a fallback, it is necessary for some very low end CD-ROM players and " "Ethernet cards. This method should generally be avoided, but a number of " "devices are listed in this section because they were added prior to the " "recognition of the OEM nature of the PC Card business. " "When adding new devices, prefer using the numeric method." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23553 msgid "Format of pccarddevs" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23555 msgid "" "There are four sections in the pccarddevs files. The " "first section lists the manufacturer numbers for vendors that use them. This " "section is sorted in numerical order. The next section has all of the " "products that are used by these vendors, along with their product ID numbers " "and a description string. The description string typically is not used " "(instead we set the device's description based on the human readable CIS, " "even if we match on the numeric version). These two sections are then " "repeated for devices that use the string matching method. Finally, C-style " "comments enclosed in /* and */ " "characters are allowed anywhere in the file." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23569 msgid "" "The first section of the file contains the vendor IDs. Please keep this list " "sorted in numeric order. Also, please coordinate changes to this file " "because we share it with NetBSD to help facilitate a common clearing house " "for this information. For example, here are the first few vendor IDs:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23576 #, no-wrap msgid "" "vendor FUJITSU 0x0004 Fujitsu Corporation\n" "vendor NETGEAR_2 0x000b Netgear\n" "vendor PANASONIC 0x0032 Matsushita Electric Industrial Co.\n" "vendor SANDISK 0x0045 Sandisk Corporation" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23581 msgid "" "Chances are very good that the NETGEAR_2 entry is really " "an OEM that NETGEAR purchased cards from and the author of support for those " "cards was unaware at the time that Netgear was using someone else's ID. " "These entries are fairly straightforward. The vendor keyword denotes the " "kind of line that this is, followed by the name of the vendor. This name " "will be repeated later in pccarddevs, as well as used " "in the driver's match tables, so keep it short and a valid C identifier. A " "numeric ID in hex identifies the manufacturer. Do not add IDs of the form " "0xffffffff or 0xffff because these are " "reserved IDs (the former is no ID set while the latter is " "sometimes seen in extremely poor quality cards to try to indicate " "none). Finally there is a string description of the company " "that makes the card. This string is not used in FreeBSD for anything but " "commentary purposes." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23600 msgid "" "The second section of the file contains the products. As shown in this " "example, the format is similar to the vendor lines:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23604 #, no-wrap msgid "" "/* Allied Telesis K.K. */\n" "product ALLIEDTELESIS LA_PCM 0x0002 Allied Telesis LA-PCM\n" "\n" "/* Archos */\n" "product ARCHOS ARC_ATAPI 0x0043 MiniCD" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23610 msgid "" "The product keyword is followed by the vendor name, " "repeated from above. This is followed by the product name, which is used by " "the driver and should be a valid C identifier, but may also start with a " "number. As with the vendors, the hex product ID for this card follows the " "same convention for 0xffffffff and 0xffff. Finally, there is a string description of the device itself. This " "string typically is not used in FreeBSD, since FreeBSD's pccard bus driver " "will construct a string from the human readable CIS entries, but it can be " "used in the rare cases where this is somehow insufficient. The products are " "in alphabetical order by manufacturer, then numerical order by product ID. " "They have a C comment before each manufacturer's entries and there is a " "blank line between entries." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23627 msgid "" "The third section is like the previous vendor section, but with all of the " "manufacturer numeric IDs set to -1, meaning match " "anything found in the FreeBSD pccard bus code. Since these are C " "identifiers, their names must be unique. Otherwise the format is identical " "to the first section of the file." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23635 msgid "" "The final section contains the entries for those cards that must be " "identified by string entries. This section's format is a little different " "from the generic section:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23639 #, no-wrap msgid "" "product ADDTRON AWP100 { \"Addtron\", \"AWP-" "100&spWireless&spPCMCIA\", \"Version&sp01.02\", NULL }\n" "product ALLIEDTELESIS WR211PCM { \"Allied&spTelesis&spK.K.\", " "\"WR211PCM\", NULL, NULL } Allied Telesis WR211PCM" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23642 msgid "" "The familiar product keyword is followed by the vendor " "name and the card name, just as in the second section of the file. Here the " "format deviates from that used earlier. There is a {} grouping, followed by " "a number of strings. These strings correspond to the vendor, product, and " "extra information that is defined in a CIS_INFO tuple. These strings are " "filtered by the program that generates pccarddevs.h to " "replace &sp with a real space. NULL strings mean that the corresponding " "part of the entry should be ignored. The example shown here contains a bad " "entry. It should not contain the version number unless that is critical for " "the operation of the card. Sometimes vendors will have many different " "versions of the card in the field that all work, in which case that " "information only makes it harder for someone with a similar card to use it " "with FreeBSD. Sometimes it is necessary when a vendor wishes to sell many " "different parts under the same brand due to market considerations " "(availability, price, and so forth). Then it can be critical to " "disambiguating the card in those rare cases where the vendor kept the same " "manufacturer/product pair. Regular expression matching is not available at " "this time." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23667 msgid "Sample Probe Routine" msgstr "" #. (itstool) path: sect2/indexterm #: book.translate.xml:23669 msgid "PC Card probe" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23674 msgid "" "To understand how to add a device to the list of supported devices, one must " "understand the probe and/or match routines that many drivers have. It is " "complicated a little in FreeBSD 5.x because there is a compatibility layer " "for OLDCARD present as well. Since only the window-dressing is different, an " "idealized version will be presented here." msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23681 #, no-wrap msgid "" "static const struct pccard_product wi_pccard_products[] = {\n" " PCMCIA_CARD(3COM, 3CRWE737A, 0),\n" " PCMCIA_CARD(BUFFALO, WLI_PCM_S11, 0),\n" " PCMCIA_CARD(BUFFALO, WLI_CF_S11G, 0),\n" " PCMCIA_CARD(TDK, LAK_CD011WL, 0),\n" " { NULL }\n" "};\n" "\n" "static int\n" "wi_pccard_probe(dev)\n" " device_t dev;\n" "{\n" " const struct pccard_product *pp;\n" "\n" " if ((pp = pccard_product_lookup(dev, wi_pccard_products,\n" " sizeof(wi_pccard_products[0]), NULL)) != NULL) {\n" " if (pp->pp_name != NULL)\n" " device_set_desc(dev, pp->pp_name);\n" " return (0);\n" " }\n" " return (ENXIO);\n" "}" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23704 msgid "" "Here we have a simple pccard probe routine that matches a few devices. As " "stated above, the name may vary (if it is not foo_pccard_probe() it will be foo_pccard_match()). The function " "pccard_product_lookup() is a generalized function that " "walks the table and returns a pointer to the first entry that it matches. " "Some drivers may use this mechanism to convey additional information about " "some cards to the rest of the driver, so there may be some variance in the " "table. The only requirement is that each row of the table must have a " "struct pccard_product as the first element." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23718 msgid "" "Looking at the table wi_pccard_products, one notices that all the entries are of the form " "PCMCIA_CARD(foo, bar, baz). The " "foo part is the manufacturer ID from " "pccarddevs. The bar part is " "the product ID. baz is the expected function " "number for this card. Many pccards can have multiple functions, and some way " "to disambiguate function 1 from function 0 is needed. You may see " "PCMCIA_CARD_D, which includes the device description from " "pccarddevs. You may also see PCMCIA_CARD2 and PCMCIA_CARD2_D which are used when you need " "to match both CIS strings and manufacturer numbers, in the use the " "default description and take the description from pccarddevs flavors." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23741 msgid "Putting it All Together" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23743 msgid "" "To add a new device, one must first obtain the identification information " "from the device. The easiest way to do this is to insert the device into a " "PC Card or CF slot and issue devinfo -v. Sample output:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23749 #, no-wrap msgid "" " cbb1 pnpinfo vendor=0x104c device=0xac51 subvendor=0x1265 subdevice=" "0x0300 class=0x060700 at slot=10 function=1\n" " cardbus1\n" " pccard1\n" " unknown pnpinfo manufacturer=0x026f product=0x030c cisvendor=" "\"BUFFALO\" cisproduct=\"WLI2-CF-S11\" function_type=6 at function=0" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23754 msgid "" "manufacturer and product are the " "numeric IDs for this product, while cisvendor and " "cisproduct are the product description strings from the " "CIS." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23760 msgid "" "Since we first want to prefer the numeric option, first try to construct an " "entry based on that. The above card has been slightly fictionalized for the " "purpose of this example. The vendor is BUFFALO, which we see already has an " "entry:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23766 #, no-wrap msgid "vendor BUFFALO 0x026f BUFFALO (Melco Corporation)" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23768 msgid "But there is no entry for this particular card. Instead we find:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23771 #, no-wrap msgid "" "/* BUFFALO */\n" "product BUFFALO WLI_PCM_S11 0x0305 BUFFALO AirStation 11Mbps WLAN\n" "product BUFFALO LPC_CF_CLT 0x0307 BUFFALO LPC-CF-CLT\n" "product BUFFALO LPC3_CLT 0x030a BUFFALO LPC3-CLT Ethernet Adapter\n" "product BUFFALO WLI_CF_S11G 0x030b BUFFALO AirStation 11Mbps CF WLAN" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23777 msgid "" "To add the device, we can just add this entry to pccarddevs:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23780 #, no-wrap msgid "" "product BUFFALO WLI2_CF_S11G 0x030c BUFFALO AirStation ultra 802.11b CF" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23782 msgid "" "Once these steps are complete, the card can be added to the driver. That is " "a simple operation of adding one line:" msgstr "" #. (itstool) path: sect2/programlisting #: book.translate.xml:23786 #, no-wrap msgid "" "static const struct pccard_product wi_pccard_products[] = {\n" " PCMCIA_CARD(3COM, 3CRWE737A, 0),\n" " PCMCIA_CARD(BUFFALO, WLI_PCM_S11, 0),\n" " PCMCIA_CARD(BUFFALO, WLI_CF_S11G, 0),\n" "+ PCMCIA_CARD(BUFFALO, WLI_CF2_S11G, 0),\n" " PCMCIA_CARD(TDK, LAK_CD011WL, 0),\n" " { NULL }\n" "};" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23795 msgid "" "Note that I have included a '+' in the line before the " "line that I added, but that is simply to highlight the line. Do not add it " "to the actual driver. Once you have added the line, you can recompile your " "kernel or module and test it. If the device is recognized and works, please " "submit a patch. If it does not work, please figure out what is needed to " "make it work and submit a patch. If the device is not recognized at all, you " "have done something wrong and should recheck each step." msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23805 msgid "" "If you are a FreeBSD src committer, and everything appears to be working, " "then you can commit the changes to the tree. However, there are some minor " "tricky things to be considered. pccarddevs must be " "committed to the tree first. Then pccarddevs.h must be " "regenerated and committed as a second step, ensuring that the right " "$FreeBSD$ tag is in the latter file. Finally, commit the additions to the " "driver." msgstr "" #. (itstool) path: sect2/title #: book.translate.xml:23816 msgid "Submitting a New Device" msgstr "" #. (itstool) path: sect2/para #: book.translate.xml:23818 msgid "" "Please do not send entries for new devices to the author directly. Instead, " "submit them as a PR and send the author the PR number for his records. This " "ensures that entries are not lost. When submitting a PR, it is unnecessary " "to include the pccardevs.h diffs in the patch, since " "those will be regenerated. It is necessary to include a description of the " "device, as well as the patches to the client driver. If you do not know the " "name, use OEM99 as the name, and the author will adjust OEM99 accordingly " "after investigation. Committers should not commit OEM99, but instead find " "the highest OEM entry and commit one more than that." msgstr "" #. (itstool) path: part/title #: book.translate.xml:23880 msgid "Appendices" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:23886 msgid "" "MarshallKirkMcKusick" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:23887 msgid "" "KeithBostic" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:23888 msgid "" "MichaelJKarels" msgstr "" #. (itstool) path: authorgroup/author #: book.translate.xml:23889 msgid "" "JohnSQuarterman" msgstr "" #. (itstool) path: biblioentry/copyright #: book.translate.xml:23892 msgid "" "1996 Addison-Wesley Publishing Company, Inc." msgstr "" #. (itstool) path: biblioentry/biblioid #: book.translate.xml:23897 msgid "0-201-54979-4" msgstr "" #. (itstool) path: publisher/publishername #: book.translate.xml:23900 msgid "Addison-Wesley Publishing Company, Inc." msgstr "" #. (itstool) path: biblioentry/citetitle #: book.translate.xml:23903 msgid "The Design and Implementation of the 4.4 BSD Operating System" msgstr "" #. (itstool) path: biblioentry/pagenums #: book.translate.xml:23905 msgid "1-2" msgstr ""