Capitolo 94.   Script e sorgenti del kernel

94.1   os32: directory principale

94.1.1   applic.sep.ld

Si veda la sezione 84.1.3.

  10001 /*****************************************************
  10002  * SEPARATED text from data
  10003  *****************************************************/
  10004 
  10005 ENTRY (startup)
  10006 SECTIONS {
  10007     . = 0x0;
  10008     _text_start = .;
  10009     .text : {
  10010         *(.text)
  10011         . = ALIGN (0x4);
  10012     }
  10013     _text_end = .;
  10014     . = 0x0;
  10015     _data_start = .;
  10016     .rodata : {
  10017         *(.rodata)
  10018         . = ALIGN (0x4);
  10019     }
  10020     .data : {
  10021         *(.data)
  10022         . = ALIGN (0x4);
  10023     }
  10024     _data_end = .;
  10025     _bss_start = .;
  10026     .bss : {
  10027         *(COMMON)
  10028         *(.bss)
  10029         . = ALIGN (0x4);
  10030     }
  10031     _bss_end = .;
  10032 }

94.1.2   bochs

Si veda la sezione 85.4.

  20001 #!/bin/sh
  20002 
  20003 if [ "$UID" = 0 ]
  20004 then
  20005   #   172.21.11.18                      172.21.11.16
  20006   #  >-----------point to point -----> >-------os32
  20007   #   tap0 (linux)                      net1
  20008   #
  20009   # Dal lato Linux:
  20010   #   ifconfig tap0 172.21.11.18 pointopoint \
  20011   #            172.21.11.16 netmask 255.255.255.255
  20012   #   route add -host 172.21.11.16 gw 172.21.11.18
  20013   #
  20014   # Dalla macchina 172.21.254.254:
  20015   #   route add -host 172.21.11.16 gw 172.21.11.18
  20016   #
  20017   bochs -q \
  20018     "boot: disk" \
  20019     "ata0-master: type=disk, path=disk.hda" \
  20020     "keyboard_mapping: enabled=1, \
  20021        map=/usr/share/bochs/keymaps/x11-pc-it.map" \
  20022     "keyboard_type: mf" \
  20023     "vga: none" \
  20024     "ne2k: mac=b0:c4:20:00:00:00, ioaddr=0x300, \
  20025            irq=9, ethmod=tuntap, ethdev=/dev/net/tun, \
  20026            script=./tap0" \
  20027     "i440fxsupport: enabled=1, slot1=pcivga, \
  20028                    slot2=ne2k" \
  20029     "romimage: \
  20030       file=\"/usr/share/bochs/BIOS-bochs-legacy\"" \
  20031     "megs:128"
  20032 else
  20033   bochs -q \
  20034     "boot: disk" \
  20035     "ata0-master: type=disk, path=disk.hda" \
  20036     "keyboard_mapping: enabled=1, \
  20037        map=/usr/share/bochs/keymaps/x11-pc-it.map" \
  20038     "keyboard_type: mf" \
  20039     "vga: none" \
  20040     "ne2k: mac=b0:c4:20:00:00:00, ioaddr=0x300, \
  20041            irq=9, ethmod=null" \
  20042     "i440fxsupport: enabled=1, slot1=pcivga, \
  20043                     slot2=ne2k" \
  20044     "romimage: \
  20045       file=\"/usr/share/bochs/BIOS-bochs-legacy\"" \
  20046     "megs:128"
  20047 fi

94.1.3   elf-to-os32

Si veda la sezione 84.1.3.

  30001 #!/bin/sh
  30002 #
  30003 #
  30004 #
  30005 g_sz ()
  30006 {
  30007       sed "s/^[[:space:]]*[0-9]*[[:space:]]*//" \
  30008     | sed "s/\.[^[:space:]]*[[:space:]]*//" \
  30009     | sed "s/\([0-9a-z]*\)[[:space:]].*$/\1/"
  30010 }
  30011 #
  30012 g_vma ()
  30013 {
  30014       sed "s/^[[:space:]]*[0-9]*[[:space:]]*//" \
  30015     | sed "s/\.[^[:space:]]*[[:space:]]*//" \
  30016     | sed "s/[0-9a-f]*[[:space:]]*//" \
  30017     | sed "s/\([0-9a-z]*\)[[:space:]].*$/\1/"
  30018 }
  30019 #
  30020 g_st ()
  30021 {
  30022       sed "s/^[[:space:]]*[0-9]*[[:space:]]*//" \
  30023     | sed "s/\.[^[:space:]]*[[:space:]]*//" \
  30024     | sed "s/[0-9a-f]*[[:space:]]*//" \
  30025     | sed "s/[0-9a-f]*[[:space:]]*//" \
  30026     | sed "s/[0-9a-f]*[[:space:]]*//" \
  30027     | sed "s/\([0-9a-z]*\)[[:space:]].*$/\1/"
  30028 }
  30029 #
  30030 FILE_ELF="$1"
  30031 FILE_OS32="$2"
  30032 #
  30033 if [ -e "$FILE_ELF" ]
  30034 then
  30035     true
  30036 else
  30037     exit
  30038 fi
  30039 #
  30040 T_ST=`objdump -h $FILE_ELF | grep -F ".text" | g_st`
  30041 T_VM=`objdump -h $FILE_ELF | grep -F ".text" | g_vma`
  30042 T_SZ=`objdump -h $FILE_ELF | grep -F ".text" | g_sz`
  30043 #
  30044 R_ST=`objdump -h $FILE_ELF | grep -F ".rodata" | g_st`
  30045 R_VM=`objdump -h $FILE_ELF | grep -F ".rodata" | g_vma`
  30046 R_SZ=`objdump -h $FILE_ELF | grep -F ".rodata" | g_sz`
  30047 #
  30048 D_ST=`objdump -h $FILE_ELF | grep -F ".data" | g_st`
  30049 D_VM=`objdump -h $FILE_ELF | grep -F ".data" | g_vma`
  30050 D_SZ=`objdump -h $FILE_ELF | grep -F ".data" | g_sz`
  30051 #
  30052 # Convert to decimal
  30053 #
  30054 T_ST=`printf "%i" 0x$T_ST`
  30055 T_VM=`printf "%i" 0x$T_VM`
  30056 T_SZ=`printf "%i" 0x$T_SZ`
  30057 #
  30058 R_ST=`printf "%i" 0x$R_ST`
  30059 R_VM=`printf "%i" 0x$R_VM`
  30060 R_SZ=`printf "%i" 0x$R_SZ`
  30061 #
  30062 D_ST=`printf "%i" 0x$D_ST`
  30063 D_VM=`printf "%i" 0x$D_VM`
  30064 D_SZ=`printf "%i" 0x$D_SZ`
  30065 
  30066 
  30067 if [ "$R_SZ" = "$D_VM" ]
  30068 then
  30069     dd if=$FILE_ELF of=$FILE_OS32.text \
  30070        bs=1 skip=$T_ST count=$T_SZ 2> "/dev/null"
  30071     dd if=$FILE_ELF of=$FILE_OS32.rodata \
  30072        bs=1 skip=$R_ST count=$R_SZ 2> "/dev/null"
  30073     dd if=$FILE_ELF of=$FILE_OS32.data \
  30074        bs=1 skip=$D_ST count=$D_SZ 2> "/dev/null"
  30075     cat $FILE_OS32.text $FILE_OS32.rodata  \
  30076         $FILE_OS32.data > $FILE_OS32
  30077     #
  30078     #rm $FILE_OS32.text
  30079     #rm $FILE_OS32.rodata
  30080     #rm $FILE_OS32.data
  30081     #
  30082     chmod a+x $FILE_OS32
  30083 elif [ "$R_SZ" -lt "$D_VM" ]
  30084 then
  30085     dd if=$FILE_ELF of=$FILE_OS32.text \
  30086        bs=1 skip=$T_ST count=$T_SZ 2> "/dev/null"
  30087     dd if=$FILE_ELF of=$FILE_OS32.rodata \
  30088        bs=1 skip=$R_ST count=$R_SZ 2> "/dev/null"
  30089     dd if=/dev/zero of=$FILE_OS32.rodata-space \
  30090        bs=1 count=$(($D_VM-$R_SZ)) 2> "/dev/null"
  30091     dd if=$FILE_ELF of=$FILE_OS32.data \
  30092        bs=1 skip=$D_ST count=$D_SZ 2> "/dev/null"
  30093 
  30094     cat $FILE_OS32.text \
  30095         $FILE_OS32.rodata \
  30096         $FILE_OS32.rodata-space \
  30097         $FILE_OS32.data > $FILE_OS32
  30098     #
  30099     #rm $FILE_OS32.text
  30100     #rm $FILE_OS32.rodata
  30101     #rm $FILE_OS32.rodata-space
  30102     #rm $FILE_OS32.data
  30103     #
  30104     chmod a+x $FILE_OS32
  30105 else
  30106     echo "[$0] ERROR: $FILE_ELF has DATA section"
  30107     echo "[$0]        not contiguous:"
  30108     echo "[$0]        RODATA end at $R_SZ, and DATA"
  30109     echo "[$0]        should start at $D_VM!"
  30110 fi

94.1.4   fdisk

Si veda la sezione 85.1.

  40001 #!/bin/sh
  40002 #
  40003 #
  40004 #
  40005 . ./file_image_functions
  40006 #
  40007 if [ -z "$1" ]
  40008 then
  40009     echo "$0 DISK_IMAGE_FILE"
  40010 else
  40011     file_image_fdisk "$1"
  40012 fi
  40013 #

94.1.5   file_image_functions

Si veda la sezione 85.1.

  50001 #
  50002 # file_image_fdisk IMAGE_FILE
  50003 #
  50004 file_image_fdisk () {
  50005   #
  50006   local FNAME="$1"
  50007   local FSIZE=0
  50008   local CYLINDERS=0
  50009   local HEADS=0
  50010   local SECTORS=63
  50011   #
  50012   if   [ -z "$FNAME" ]
  50013   then
  50014       echo "[$0] No file name."
  50015       return 1
  50016   elif [ ! -r "$FNAME" ]
  50017   then
  50018       echo "[$0] Cannot read file \"$FNAME\"."
  50019       return 1
  50020   fi
  50021   #
  50022   # Get size
  50023   #
  50024   FSIZE=`du -k "$FNAME" | sed "s/[[:space:]].*$//"`
  50025   #
  50026   # Set geometry
  50027   #
  50028   if [ "$FSIZE" -le "516096" ]
  50029   then
  50030       HEADS="16"
  50031   else
  50032       HEADS="255"
  50033   fi
  50034   #
  50035   CYLINDERS=$(($FSIZE*2/$SECTORS/$HEADS))
  50036   #
  50037   # Run fdisk.
  50038   #
  50039   fdisk -C $CYLINDERS -H $HEADS -S $SECTORS $FNAME
  50040 }
  50041 #
  50042 # file_image_partition_start IMAGE_FILE PART_NUMBER
  50043 #
  50044 file_image_partition_start () {
  50045   #
  50046   local FNAME="$1"
  50047   local PART_NUMBER="$2"
  50048   local PART_START=0
  50049   #
  50050   # Get partition start
  50051   #
  50052   PART_START=`sfdisk -d $FNAME \
  50053     | grep -F "$FNAME$PART_NUMBER" \
  50054     | sed "s/^.*start=[[:space:]]*//" | sed "s/,.*$//"`
  50055   #
  50056   echo "$PART_START"
  50057 }
  50058 #
  50059 # file_image_partition_size IMAGE_FILE PART_NUMBER
  50060 #
  50061 file_image_partition_size () {
  50062   #
  50063   local FNAME="$1"
  50064   local PART_NUMBER="$2"
  50065   local PART_SIZE=0
  50066   #
  50067   # Get partition start
  50068   #
  50069   PART_SIZE=`sfdisk -d $FNAME \
  50070     | grep -F "$FNAME$PART_NUMBER" \
  50071     | sed "s/^.*size=[[:space:]]*//" | sed "s/,.*$//"`
  50072   #
  50073   echo "$PART_SIZE"
  50074 }
  50075 #
  50076 # file_image_partition_id IMAGE_FILE PART_NUMBER
  50077 #
  50078 file_image_partition_id () {
  50079   #
  50080   local FNAME="$1"
  50081   local PART_NUMBER="$2"
  50082   local PART_ID=0
  50083   #
  50084   # Get partition start
  50085   #
  50086   PART_ID=`sfdisk -d $FNAME \
  50087    | grep -F "$FNAME$PART_NUMBER" \
  50088    | sed "s/^.*Id=[[:space:]]*//" | sed "s/,.*$//"`
  50089   #
  50090   echo "$PART_ID"
  50091 }
  50092 #
  50093 # file_image_partition_format IMAGE_FILE PART_NUMBER \
  50094 #                             [dos|minix]
  50095 #
  50096 file_image_partition_format () {
  50097   #
  50098   local FNAME="$1"
  50099   local PART_NUMBER="$2"
  50100   local PART_FORMAT="$3"
  50101   local PART_START=`file_image_partition_start \
  50102                     $FNAME $PART_NUMBER`
  50103   local PART_SIZE=`file_image_partition_size $FNAME \
  50104                    $PART_NUMBER`
  50105   local PART_ID=`file_image_partition_id $FNAME \
  50106                  $PART_NUMBER`
  50107   #
  50108   #
  50109   #
  50110   if [ "$PART_SIZE" -eq "0" ]
  50111   then
  50112       exit
  50113   fi
  50114   #
  50115   # Get partition into a file.
  50116   #
  50117   dd if="$FNAME" \
  50118      of="$FNAME.part$PART_NUMBER.tmp" \
  50119      bs=512 \
  50120      skip="$PART_START" \
  50121      count="$PART_SIZE"
  50122   #
  50123   # Format.
  50124   #
  50125   if [ "$PART_FORMAT" = "dos" ] \
  50126     || [ "$PART_FORMAT" = "msdos" ]
  50127   then
  50128       mkfs.msdos -v "$FNAME.part$PART_NUMBER.tmp"
  50129   else
  50130       mkfs.minix -n 14 "$FNAME.part$PART_NUMBER.tmp"
  50131   fi
  50132   #
  50133   # Put formatted partition into the file.
  50134   #
  50135   dd if="$FNAME.part$PART_NUMBER.tmp" \
  50136      of="$FNAME" \
  50137      bs=512 \
  50138      seek="$PART_START" \
  50139      count="$PART_SIZE" \
  50140      conv=notrunc
  50141   #
  50142   # Remove temporary file.
  50143   #
  50144   rm "$FNAME.part$PART_NUMBER.tmp"
  50145   #
  50146 }
  50147 #
  50148 # file_image_partition_mount IMAGE_FILE PART_NUMBER
  50149 #
  50150 file_image_partition_mount () {
  50151   #
  50152   local FNAME="$1"
  50153   local PART_NUMBER="$2"
  50154   local PART_START=`file_image_partition_start \
  50155                     $FNAME $PART_NUMBER`
  50156   local PART_SIZE=`file_image_partition_size \
  50157                    $FNAME $PART_NUMBER`
  50158   local PART_ID=`file_image_partition_id \
  50159                  $FNAME $PART_NUMBER`
  50160   local MOUNT_POINT
  50161   #
  50162   #
  50163   #
  50164   if [ "$PART_SIZE" -eq "0" ]
  50165   then
  50166       exit
  50167   fi
  50168   #
  50169   # Find mount point.
  50170   #
  50171   MOUNT_POINT=`basename $FNAME`
  50172   MOUNT_POINT="/mnt/${MOUNT_POINT}.$PART_NUMBER"
  50173   #
  50174   #
  50175   #
  50176   sync
  50177   #
  50178   umount "$MOUNT_POINT" 2> "/dev/null"
  50179   umount "$MOUNT_POINT" 2> "/dev/null"
  50180   umount "$MOUNT_POINT" 2> "/dev/null"
  50181   #
  50182   mkdir -p "$MOUNT_POINT" 2> "/dev/null"
  50183   #
  50184   # Get partition into a file.
  50185   #
  50186   dd if="$FNAME" \
  50187      of="$FNAME.part$PART_NUMBER.tmp" \
  50188      bs=512 \
  50189      skip="$PART_START" \
  50190      count="$PART_SIZE"
  50191   #
  50192   # Check partition.
  50193   #
  50194   fsck -f -v -r "$FNAME.part$PART_NUMBER.tmp"
  50195   #
  50196   # Put formatted partition into the file.
  50197   #
  50198   dd if="$FNAME.part$PART_NUMBER.tmp" \
  50199      of="$FNAME" \
  50200      bs=512 \
  50201      seek="$PART_START" \
  50202      count="$PART_SIZE" \
  50203      conv=notrunc
  50204   #
  50205   # Remove temporary file.
  50206   #
  50207   rm "$FNAME.part$PART_NUMBER.tmp"
  50208   #
  50209   # Mount the partition.
  50210   #
  50211   mount -o loop,offset=$(($PART_START*512)) \
  50212         -t auto "$FNAME" "$MOUNT_POINT"
  50213   #
  50214 }
  50215 #
  50216 # file_image_partition_syslinux IMAGE_FILE PART_NUMBER
  50217 #
  50218 file_image_partition_syslinux () {
  50219   #
  50220   local FNAME="$1"
  50221   local PART_NUMBER="$2"
  50222   local PART_START=`file_image_partition_start \
  50223                     $FNAME $PART_NUMBER`
  50224   local PART_SIZE=`file_image_partition_size \
  50225                    $FNAME $PART_NUMBER`
  50226   local PART_ID=`file_image_partition_id \
  50227                  $FNAME $PART_NUMBER`
  50228   #
  50229   #
  50230   #
  50231   if [ "$PART_SIZE" -eq "0" ]
  50232   then
  50233       exit
  50234   fi
  50235   #
  50236   # Get partition into a file.
  50237   #
  50238   dd if="$FNAME" \
  50239      of="$FNAME.part$PART_NUMBER.tmp" \
  50240      bs=512 \
  50241      skip="$PART_START" \
  50242      count="$PART_SIZE"
  50243   #
  50244   # Syslinux
  50245   #
  50246   syslinux "$FNAME.part$PART_NUMBER.tmp"
  50247   #
  50248   # Put altered partition into the file.
  50249   #
  50250   dd if="$FNAME.part$PART_NUMBER.tmp" \
  50251      of="$FNAME" \
  50252      bs=512 \
  50253      seek="$PART_START" \
  50254      count="$PART_SIZE" \
  50255      conv=notrunc
  50256   #
  50257   # Remove temporary file.
  50258   #
  50259   rm "$FNAME.part$PART_NUMBER.tmp"
  50260   #
  50261   # Fix MBR
  50262   #
  50263   install-mbr $FNAME
  50264 }
  50265 

94.1.6   format

Si veda la sezione 85.1.

  60001 #!/bin/sh
  60002 #
  60003 #
  60004 #
  60005 . ./file_image_functions
  60006 #
  60007 if [ -z "$1" ] \
  60008   || [ -z "$2" ] \
  60009   || [ "$2" -lt "1" ] \
  60010   || [ "$2" -gt "4" ]
  60011 then
  60012     echo "Usage:"
  60013     echo ""
  60014     echo "$0 DISK_IMAGE_FILE PART_NUMBER dos|minix"
  60015     echo ""
  60016     echo "The partition number must be between"
  60017     echo " 1 and 4. No extended partitions are"
  60018     echo "handled!"
  60019 else
  60020     file_image_partition_format "$1" "$2" "$3"
  60021 fi
  60022 #

94.1.7   kernel.ld

Si veda la sezione 84.2.2.

  70001 /*****************************************************
  70002  * The code will start at address 0x100000, that is at
  70003  * 1 Mibyte, because it is the place where GRUB will
  70004  * place it.
  70005  *
  70006  * The kernel is divided into `TEXT' (code), `DATA' and
  70007  * `BSS'.
  70008  * Between the TEXT and the DATA there is a gap to
  70009  * align the data at 4 Kibyte boundary (0x1000), to
  70010  * allow memory management for it.
  70011  *
  70012  * The stack will be placed at the beginning of the
  70013  * BSS.
  70014  *
  70015  * The kernel starts with file `kernel/main/crt0.s',
  70016  * at the label `startup'.
  70017  *****************************************************/
  70018 ENTRY (kstartup)
  70019 SECTIONS {
  70020     . = 0x00100000;
  70021     _k_start = .;
  70022     _k_text_start = .;
  70023     .text : {
  70024         *(.text)
  70025     }
  70026     _k_text_end = .;
  70027     . = ALIGN (0x1000);
  70028     _k_data_start = .;
  70029     .rodata : {
  70030         *(.rodata)
  70031     }
  70032     . = ALIGN (0x4);
  70033     .data : {
  70034         *(.data)
  70035     }
  70036     _k_data_end = .;
  70037     . = ALIGN (0x4);
  70038     _k_bss_start = .;
  70039     .bss : {
  70040         *(COMMON)
  70041         *(.bss)
  70042     }
  70043     _k_bss_end = .;
  70044     _k_end = .;
  70045 }

94.1.8   makeit.sep

Si veda la sezione 91.3.

  80001 #!/bin/sh
  80002 #
  80003 # makeit... separated: text and data have separate
  80004 # segments.
  80005 #
  80006 OPTION="$1"
  80007 OS32PATH=""
  80008 #
  80009 #
  80010 #
  80011 edition () {
  80012   local EDITION="kernel/main/build.h"
  80013   echo -n                              > $EDITION
  80014   echo -n "#define BUILD_DATE \""     >> $EDITION
  80015   echo -n `date "+%Y%m%d%H%M"`        >> $EDITION
  80016   echo  "\""  >> $EDITION
  80017 }
  80018 #
  80019 #
  80020 #
  80021 makefile () {
  80022   #
  80023   local MAKEFILE="Makefile"
  80024   local TAB=`printf "\t"`
  80025   #
  80026   local SOURCE_C=""
  80027   local C=""
  80028   local SOURCE_S=""
  80029   local S=""
  80030   #
  80031   local c
  80032   local s
  80033   #
  80034   # Find C source files.
  80035   #
  80036   for c in *.c
  80037   do
  80038       if [ -f $c ]
  80039       then
  80040       C=`basename $c .c`
  80041           SOURCE_C="$SOURCE_C $C"
  80042       fi
  80043   done
  80044   #
  80045   # Find ASM source files.
  80046   #
  80047   for s in *.s
  80048   do
  80049       if [ -f $s ]
  80050       then
  80051       S=`basename $s .s`
  80052           SOURCE_S="$SOURCE_S $S"
  80053       fi
  80054   done
  80055   #
  80056   # Prepare the Makefile. Option `-g' is for debugging
  80057   # symbols.
  80058   #
  80059   echo -n                                   > $MAKEFILE
  80060   echo "# This file was made "             >> $MAKEFILE
  80061   echo "# automatically"                   >> $MAKEFILE
  80062   echo "# by the script \`makeit', based"  >> $MAKEFILE
  80063   echo "# on the directory content."       >> $MAKEFILE
  80064   echo "# Please use \`makeit' to "        >> $MAKEFILE
  80065   echo "# compile and"                     >> $MAKEFILE
  80066   echo "# \`makeit clean\' to clean "      >> $MAKEFILE
  80067   echo "# directories."                    >> $MAKEFILE
  80068   echo "#"                                 >> $MAKEFILE
  80069   echo "#"                                 >> $MAKEFILE
  80070   echo "c = $SOURCE_C"                     >> $MAKEFILE
  80071   echo "#"                                 >> $MAKEFILE
  80072   echo "s = $SOURCE_S"                     >> $MAKEFILE
  80073   echo "#"                                 >> $MAKEFILE
  80074   echo "all: \$(s) \$(c)"                  >> $MAKEFILE
  80075   echo "#"                                 >> $MAKEFILE
  80076   echo "clean:"                            >> $MAKEFILE
  80077   echo "${TAB}@rm *~ *.o *.ELF *.text " \
  80078        "*.rodata *.rodata-space " \
  80079        "*.data \$(c) 2> /dev/null ; pwd"   >> $MAKEFILE
  80080   echo "#"                                 >> $MAKEFILE
  80081   echo "\$(s):"                            >> $MAKEFILE
  80082   echo "${TAB}@echo \$@.s"                 >> $MAKEFILE
  80083   echo "${TAB}@as -o \$@.o \$@.s"          >> $MAKEFILE
  80084   echo "#"                                 >> $MAKEFILE
  80085   echo "\$(c):"                            >> $MAKEFILE
  80086   echo "${TAB}@echo \$@.c"                 >> $MAKEFILE
  80087   echo "${TAB}@gcc -O0 -Wall -Werror "    \
  80088        "-Wno-unused-but-set-variable"     \
  80089        "-g"                           \
  80090        "-o \$@.o -c \$@.c"            \
  80091        "-nostdinc -nostdlib "         \
  80092        "-nostartfiles -nodefaultlibs" \
  80093        "-I " \
  80094        "-I. " \
  80095        "-I$OS32PATH/lib " \
  80096        "-I$OS32PATH/ " \
  80097        "-I../include -I../../include " \
  80098        "-I../../../include"  >> $MAKEFILE
  80099   #
  80100 }
  80101 #
  80102 #
  80103 #
  80104 main () {
  80105   #
  80106   local CURDIR=`pwd`
  80107   local OBJECTS
  80108   local d
  80109   local c
  80110   local s
  80111   local o
  80112   #
  80113   edition
  80114   #
  80115   # Copia dello scheletro
  80116   #
  80117   if [ "$OPTION" = "clean" ]
  80118   then
  80119       #
  80120       # La copia non va fatta.
  80121       #
  80122       true
  80123   else
  80124       cp -dpRv skel/etc   /mnt/disk.hda.2/
  80125       cp -dpRv skel/dev   /mnt/disk.hda.2/
  80126       mkdir               /mnt/disk.hda.2/mnt/
  80127       mkdir               /mnt/disk.hda.2/tmp/
  80128       chmod 0777          /mnt/disk.hda.2/tmp/
  80129       mkdir               /mnt/disk.hda.2/usr/
  80130       mkdir               /mnt/disk.hda.2/var/
  80131       cp -dpRv skel/root  /mnt/disk.hda.2/
  80132       cp -dpRv skel/home  /mnt/disk.hda.2/
  80133       cp -dpRv skel/usr/* /mnt/disk.hda.2/usr/
  80134       cp -dpRv skel/var/* /mnt/disk.hda.2/var/
  80135   fi
  80136   #
  80137   for d in `find .`
  80138   do
  80139     if [ -d "$d" ]
  80140     then
  80141       #
  80142       # Are there C or ASM source files?
  80143       #
  80144       c=`echo $d/*.c | sed "s/ .*//"`
  80145       s=`echo $d/*.s | sed "s/ .*//"`
  80146       #
  80147       if [ -f "$c" ] || [ -f "$s" ]
  80148       then
  80149           CURDIR=`pwd`
  80150           cd $d
  80151           #
  80152           # Build the new makefile
  80153           #
  80154           makefile
  80155           #
  80156           # Clean the directory
  80157           #
  80158           make clean
  80159           #
  80160           #
  80161           #
  80162           if [ "$OPTION" = "clean" ]
  80163           then
  80164               #
  80165               # Nothing else to do: the clean was
  80166               # just made.
  80167               #
  80168               true
  80169           else
  80170               if ! make
  80171               then
  80172                   cd "$CURDIR"
  80173                   exit
  80174               fi
  80175           fi
  80176           cd "$CURDIR"
  80177       fi
  80178     fi
  80179   done
  80180   #
  80181   cd "$CURDIR"
  80182   #
  80183   #
  80184   #
  80185   if [ "$OPTION" = "clean" ]
  80186   then
  80187     true
  80188   else
  80189     #
  80190     echo "Link kernel"
  80191     #
  80192     OBJECTS=""
  80193     #
  80194     for o in `find . -name \*.o -print`
  80195     do
  80196       if    [ "$o" = "./kernel/main/crt0.o" ] \
  80197         || [ "$o" = "./kernel/main/kmain.o" ] \
  80198         || [ "$o" = "./kernel/main/stack.o" ] \
  80199         || [ ! -e "$o" ] \
  80200         || echo "$o" | grep -F "./applic/" \
  80201             > "/dev/null" \
  80202         || echo "$o" | grep -F "./ported/" \
  80203             > "/dev/null"
  80204       then
  80205         true
  80206       else
  80207         OBJECTS="$OBJECTS $o"
  80208       fi
  80209     done
  80210     #
  80211     # The kernel must be ELF, because Grub will not
  80212     # recognize it otherwise.
  80213     #
  80214     ld  --script=kernel.ld \
  80215         --oformat elf32-i386 \
  80216         -o kimage \
  80217         ./kernel/main/crt0.o \
  80218         $OBJECTS \
  80219         ./kernel/main/kmain.o \
  80220         ./kernel/main/stack.o
  80221     #
  80222     cp -f kimage /mnt/disk.hda.1/kimage
  80223     sync
  80224     #
  80225     # Collegamento delle applicazioni di os32.
  80226     #
  80227     OBJLIB=""
  80228     #
  80229     for o in `find lib      -name \*.o -print`
  80230     do
  80231         OBJLIB="$OBJLIB $o"
  80232     done
  80233     #
  80234     echo "Link applic"
  80235     #
  80236     # Scansione delle applicazioni interne.
  80237     #
  80238     for o in `find applic     -name \*.o -print`
  80239     do
  80240       if    [ "$o" = "applic/crt0.o" ] \
  80241         || [ ! -e "$o" ] \
  80242         || echo "$o" | grep ".crt0.o$" > /dev/null \
  80243         || echo "$o" | grep ".crt0.mer.o$" \
  80244             > /dev/null \
  80245         || echo "$o" | grep ".crt0.sep.o$" > /dev/null
  80246       then
  80247         #
  80248         # Il file non esiste oppure si tratta di
  80249         # `...crt0.s'.
  80250         #
  80251         true
  80252       else
  80253         #
  80254         # File oggetto differente da `...crt0.s'.
  80255         #
  80256         EXEC=`echo "$o" | sed "s/\.o$//"`
  80257         BASENAME=`basename $o .o`
  80258         if [ -e "applic/$BASENAME.crt0.sep.o" ]
  80259         then
  80260           #
  80261           # Qui c'è un file `...crt0.o' specifico.
  80262           #
  80263           rm $EXEC $EXEC.ELF  2> "/dev/null"
  80264           ld  --no-check-sections \
  80265               --oformat elf32-i386 \
  80266               --script=applic.sep.ld \
  80267               -o $EXEC.ELF \
  80268               ./applic/$BASENAME.crt0.sep.o \
  80269               $o \
  80270               $OBJLIB
  80271               #
  80272               ./elf-to-os32 $EXEC.ELF $EXEC
  80273         else
  80274           #
  80275           # Qui si usa il file `crt0.sep.o' generale.
  80276           #
  80277           rm $EXEC $EXEC.ELF  2> "/dev/null"
  80278           ld  --script=applic.sep.ld \
  80279               --no-check-sections \
  80280               --oformat elf32-i386 \
  80281               -o $EXEC.ELF \
  80282               ./applic/crt0.sep.o \
  80283               $o \
  80284               $OBJLIB
  80285               #
  80286               ./elf-to-os32 $EXEC.ELF $EXEC
  80287         fi
  80288         #
  80289         if [ -x "applic/$BASENAME" ]
  80290         then
  80291           if mount | grep /mnt/disk.hda.2 > /dev/null
  80292           then
  80293             mkdir /mnt/disk.hda.2/bin/ 2> /dev/null
  80294             rm /mnt/disk.hda.2/bin/$EXEC 2> "/dev/null"
  80295             cp -f "$EXEC" /mnt/disk.hda.2/bin
  80296           else
  80297             echo "[$0] Cannot copy the application"
  80298             echo "[$0]   $BASENAME inside the disk"
  80299             echo "[$0]   image!"
  80300             break
  80301           fi
  80302         fi
  80303       fi
  80304     done
  80305     sync
  80306     #
  80307     echo "Link ported"
  80308     #
  80309     # Scansione delle applicazioni adattate.
  80310     #
  80311     for a in ported/*
  80312     do
  80313       if [ -d $a ]
  80314       then
  80315         OBJECTS=""
  80316         for o in `find $a  -name \*.o -print`
  80317         do
  80318           if    [ "$o" = "$a/crt0.o" ] \
  80319             || [ ! -e "$o" ] \
  80320             || echo "$o" | grep "crt0.o$" > /dev/null \
  80321             || echo "$o" | grep "crt0.mer.o$" \
  80322                 > /dev/null \
  80323             || echo "$o" | grep "crt0.sep.o$" \
  80324                 > /dev/null
  80325           then
  80326             #
  80327             # Il file non esiste oppure si tratta di
  80328             # `...crt0.s'.
  80329             #
  80330             true
  80331           else
  80332             OBJECTS="$OBJECTS $o"
  80333           fi
  80334         done
  80335         #
  80336         # File oggetto differente da `...crt0.s'.
  80337         #
  80338         BASENAME=`basename $a`
  80339         EXEC="$a/$BASENAME"
  80340         #
  80341         rm $EXEC $EXEC.ELF  2> "/dev/null"
  80342         #
  80343         echo ld  --script=applic.sep.ld \
  80344             --no-check-sections \
  80345             --oformat elf32-i386 \
  80346             -o $EXEC.ELF \
  80347             $a/crt0.sep.o \
  80348             $OBJECTS \
  80349             $OBJLIB > link-$BASENAME.link
  80350             #
  80351         echo ./elf-to-os32 $EXEC.ELF $EXEC \
  80352              >> link-$BASENAME.link
  80353         #
  80354         ld  --script=applic.sep.ld \
  80355             --no-check-sections \
  80356             --oformat elf32-i386 \
  80357             -o $EXEC.ELF \
  80358             $a/crt0.sep.o \
  80359             $OBJECTS \
  80360             $OBJLIB
  80361             #
  80362         ./elf-to-os32 $EXEC.ELF $EXEC
  80363         #
  80364         if [ -x "$EXEC" ]
  80365         then
  80366           if mount | grep /mnt/disk.hda.2 > /dev/null
  80367           then
  80368             mkdir /mnt/disk.hda.2/bin/ 2> /dev/null
  80369             rm /mnt/disk.hda.2/bin/$EXEC 2> "/dev/null"
  80370             cp -f "$EXEC" /mnt/disk.hda.2/bin
  80371           else
  80372             echo "[$0] Cannot copy the application "
  80373             echo "[$0]   $BASENAME inside the disk "
  80374             echo "[$0]   image!"
  80375             break
  80376           fi
  80377         fi
  80378       fi
  80379     done
  80380     sync
  80381   fi
  80382 }
  80383 #
  80384 # Start.
  80385 #
  80386 if [ -d kernel ]   && \
  80387    [ -d lib  ]
  80388 then
  80389     OS32PATH=`pwd`
  80390     main
  80391 else
  80392     echo "[$0] Running from a wrong directory!"
  80393 fi

94.1.9   qemu

Si veda la sezione 85.4.

  90001 #!/bin/sh
  90002 #
  90003 #
  90004 #
  90005 if [ -n "$DISPLAY" ]
  90006 then
  90007     CURSES=""
  90008 else
  90009     CURSES="-curses"
  90010 fi
  90011 
  90012 if [ "$EUID" = "0" ]
  90013 then
  90014   #   172.21.11.18                      172.21.11.16
  90015   #  >-----------point to point -----> >-------os32
  90016   #   tap0 (linux)                      net1
  90017   #
  90018   # Dal lato Linux:
  90019   #   ifconfig tap0 172.21.11.18 pointopoint \
  90020   #            172.21.11.16 netmask 255.255.255.255
  90021   #   route add -host 172.21.11.16 gw 172.21.11.18
  90022   #
  90023   # Dalla macchina 172.21.254.254:
  90024   #   route add -host 172.21.11.16 gw 172.21.11.18
  90025   #
  90026   qemu $CURSES \
  90027     -hda disk.hda \
  90028     -net nic,macaddr=b0:c4:20:00:00:00,model=ne2k_pci \
  90029     -net tap,ifname=tap0,script=./tap0 \
  90030     -boot c
  90031 else
  90032   echo "[$0] Qemu avviato senza privilegi: non"
  90033   echo "[$0] funziona la rete!"
  90034   echo "[$0] Premi Invio per continuare"
  90035   read
  90036 
  90037   qemu $CURSES \
  90038     -hda disk.hda \
  90039     -net nic,macaddr=b0:c4:20:00:00:00,model=ne2k_pci \
  90040     -net user,net=172.21.0.0/16,host=172.21.254.254,\
  90041 restrict=n \
  90042     -boot c
  90043 fi
  90044 

94.1.10   syslinux

Si veda la sezione 85.1.

 100001 #!/bin/sh
 100002 #
 100003 #
 100004 #
 100005 . ./file_image_functions
 100006 #
 100007 if [ -z "$1" ] || [ -z "$2" ] || [ "$2" -lt "1" ] \
 100008   || [ "$2" -gt "4" ]
 100009 then
 100010     echo "Usage:"
 100011     echo ""
 100012     echo "$0 DISK_IMAGE_FILE PART_NUMBER"
 100013     echo ""
 100014     echo "The partition number must be between"
 100015     echo " 1 and 4."
 100016     echo "No extended partitions are handled!"
 100017 else
 100018     file_image_partition_syslinux "$1" "$2"
 100019 fi
 100020 #

94.1.11   tap0

Si veda la sezione 85.4.

 110001 #!/bin/sh
 110002 
 110003 
 110004 ifconfig tap0 172.21.11.18 pointopoint 172.21.11.16 \
 110005               netmask 255.255.255.255
 110006 route add -host 172.21.11.16 gw 172.21.11.18
 110007 
 110008 

94.2   os32: «kernel/blk.h»

Si veda la sezione 93.3.

 120001 #ifndef _KERNEL_BLK_H
 120002 #define _KERNEL_BLK_H 1
 120003 //----------------------------------------------------------
 120004 #include <sys/types.h>
 120005 #include <kernel/driver/ata.h>
 120006 //----------------------------------------------------------
 120007 #define BLK_SIZE          ATA_SECTOR_SIZE       // [1]
 120008 //
 120009 // [1] This value should be the same as the mass memory
 120010 //     sector size, or a multiple. But with a multiple,
 120011 //     all simple read and write will be doubled, and
 120012 //     some race will lock the system, because read and
 120013 //     write are too frequent for the poor ATA driver
 120014 //     that I have. :-(
 120015 //
 120016 //----------------------------------------------------------
 120017 #define BLK_CACHE_SIZE          128     // This is
 120018                                         // free!
 120019 #define BLK_CACHE_MAX_AGE       BLK_CACHE_SIZE-1
 120020 typedef struct
 120021 {
 120022   unsigned int age;     // 0=last used
 120023   // DEV_CACHE_MAX_AGE=older
 120024   dev_t device;
 120025   unsigned int n;
 120026   char block[BLK_SIZE];
 120027 } blk_cache_t;
 120028 
 120029 extern blk_cache_t blk_table[BLK_CACHE_SIZE];
 120030 //----------------------------------------------------------
 120031 void *blk_ata (dev_t device, int rw, unsigned int n,
 120032                void *buffer);
 120033 //----------------------------------------------------------
 120034 void blk_cache_init (void);
 120035 void blk_cache_check (void);
 120036 void *blk_cache_read (dev_t device, unsigned int n);
 120037 void *blk_cache_save (dev_t device, unsigned int n,
 120038                       void *block);
 120039 //----------------------------------------------------------
 120040 
 120041 #endif

94.2.1   kernel/blk/blk_ata.c

Si veda la sezione 93.3.1.

 130001 #include <sys/os32.h>
 130002 #include <kernel/blk.h>
 130003 #include <kernel/dev.h>
 130004 #include <kernel/driver/ata.h>
 130005 #include <kernel/lib_k.h>
 130006 #include <kernel/dm.h>
 130007 #include <sys/types.h>
 130008 #include <ctype.h>
 130009 #include <string.h>
 130010 //----------------------------------------------------------
 130011 #define DEBUG 0
 130012 //----------------------------------------------------------
 130013 void *
 130014 blk_ata (dev_t device, int rw, unsigned int n, void *buffer)
 130015 {
 130016   ata_sector_t *destination = buffer;
 130017   ata_sector_t *source = buffer;
 130018   int dev_minor = minor (device);
 130019   int d = ((dev_minor & 0x00F0) >> 4);
 130020   ptrdiff_t ptrdiff;
 130021   int drive;
 130022   unsigned int sector = n * (BLK_SIZE / ATA_SECTOR_SIZE);
 130023   size_t count = (BLK_SIZE / ATA_SECTOR_SIZE);
 130024   int status;
 130025   int c;
 130026   void *cache;
 130027   // 
 130028   // Convert the table pointer to a drive number.
 130029   // 
 130030   ptrdiff = (((intptr_t) dm_table[d].table)
 130031              - ((intptr_t) ata_table));
 130032   drive = ptrdiff / (sizeof (ata_t));
 130033   // 
 130034   if (DEBUG)
 130035     {
 130036       k_printf ("%s: R/W=%i dev=%04x n=%ui ", __FILE__,
 130037                 rw, (int) device, n);
 130038       blk_cache_check ();
 130039     }
 130040   // 
 130041   // If reading, check if we already have inside
 130042   // cache.
 130043   // 
 130044   if (rw == DEV_READ)
 130045     {
 130046       cache = blk_cache_read (device, n);
 130047       if (cache != NULL)
 130048         {
 130049           return (cache);
 130050         }
 130051     }
 130052   // 
 130053   // Read or write.
 130054   // 
 130055   for (c = 0, status = 0;
 130056        c < count && status == 0; c++, sector++)
 130057     {
 130058       // 
 130059       if (DEBUG)
 130060         {
 130061           k_printf ("sec=%i ", sector);
 130062         }
 130063       // 
 130064       if (rw == DEV_READ)
 130065         {
 130066           status = ata_read_sector (drive, sector,
 130067                                     &destination[c]);
 130068         }
 130069       else
 130070         {
 130071           status = ata_write_sector (drive, sector,
 130072                                      &source[c]);
 130073         }
 130074     }
 130075   // 
 130076   // If a block was read or written inside ATA
 130077   // hardware, then
 130078   // save it inside the cache.
 130079   // 
 130080   if (status == 0)
 130081     {
 130082       cache = blk_cache_save (device, n, buffer);
 130083     }
 130084   else
 130085     {
 130086       cache = NULL;
 130087     }
 130088   // 
 130089   // 
 130090   // 
 130091   if (DEBUG)
 130092     {
 130093       k_printf ("\n");
 130094     }
 130095   // 
 130096   return (cache);
 130097 }

94.2.2   kernel/blk/blk_cache_check.c

Si veda la sezione 93.3.2.

 140001 #include <kernel/blk.h>
 140002 #include <string.h>
 140003 #include <kernel/lib_k.h>
 140004 //----------------------------------------------------------
 140005 void
 140006 blk_cache_check (void)
 140007 {
 140008   int i;
 140009   int j;
 140010   // 
 140011   // check if all ages are present.
 140012   // 
 140013   for (i = 0; i < BLK_CACHE_SIZE; i++)
 140014     {
 140015       if (blk_table[i].age > BLK_CACHE_MAX_AGE)
 140016         {
 140017           k_printf
 140018             ("blk_table[%i].age > BLK_CACHE_MAX_AGE\n", i);
 140019           return;
 140020         }
 140021       for (j = 0; j < BLK_CACHE_SIZE; j++)
 140022         {
 140023           if (j != i
 140024               && blk_table[i].age == blk_table[j].age)
 140025             {
 140026               k_printf
 140027                 ("blk_table[%i].age == "
 140028                  "blk_table[%i].age\n", i, j);
 140029               return;
 140030             }
 140031         }
 140032     }
 140033 }

94.2.3   kernel/blk/blk_cache_init.c

Si veda la sezione 93.3.3.

 150001 #include <kernel/blk.h>
 150002 //----------------------------------------------------------
 150003 void
 150004 blk_cache_init (void)
 150005 {
 150006   int i;
 150007   for (i = 0; i < BLK_CACHE_SIZE; i++)
 150008     {
 150009       blk_table[i].age = i;     // Age is from 0 to
 150010       // BLK_CACHE_MAX_AGE.
 150011       blk_table[i].device = 0;
 150012       blk_table[i].n = 0;
 150013     }
 150014 }

94.2.4   kernel/blk/blk_cache_read.c

Si veda la sezione 93.3.4.

 160001 #include <kernel/blk.h>
 160002 #include <string.h>
 160003 //----------------------------------------------------------
 160004 void *
 160005 blk_cache_read (dev_t device, unsigned int n)
 160006 {
 160007   int i;
 160008   int j;
 160009   int age;
 160010   // 
 160011   device &= 0xFFF0;
 160012   // 
 160013   for (i = 0; i < BLK_CACHE_SIZE; i++)
 160014     {
 160015       if (blk_table[i].device == device
 160016           && blk_table[i].n == n)
 160017         {
 160018           age = blk_table[i].age;
 160019           for (j = 0; j < BLK_CACHE_SIZE; j++)
 160020             {
 160021               if (blk_table[j].age < age)
 160022                 {
 160023                   blk_table[j].age++;
 160024                 }
 160025             }
 160026           blk_table[i].age = 0;
 160027           // 
 160028           return (&blk_table[i].block);
 160029         }
 160030     }
 160031   return (NULL);
 160032 }

94.2.5   kernel/blk/blk_cache_save.c

Si veda la sezione 93.3.4.

 170001 #include <kernel/blk.h>
 170002 #include <string.h>
 170003 //----------------------------------------------------------
 170004 void *
 170005 blk_cache_save (dev_t device, unsigned int n, void *block)
 170006 {
 170007   int i;
 170008   int j;
 170009   int age;
 170010   // 
 170011   device &= 0xFFF0;
 170012   // 
 170013   // Look inside the cache, if we already have
 170014   // that old block.
 170015   // 
 170016   for (i = 0; i < BLK_CACHE_SIZE; i++)
 170017     {
 170018       if (blk_table[i].device == device
 170019           && blk_table[i].n == n)
 170020         {
 170021           age = blk_table[i].age;
 170022           for (j = 0; j < BLK_CACHE_SIZE; j++)
 170023             {
 170024               if (blk_table[j].age < age)
 170025                 {
 170026                   blk_table[j].age++;
 170027                 }
 170028             }
 170029           blk_table[i].age = 0;
 170030           // 
 170031           // Check if the block is the same memory.
 170032           // 
 170033           if (blk_table[i].block == block)
 170034             {
 170035               // 
 170036               // No need to transfer data.
 170037               // 
 170038               ;
 170039             }
 170040           else
 170041             {
 170042               memcpy (blk_table[i].block, block,
 170043                       (size_t) BLK_SIZE);
 170044             }
 170045           return (&blk_table[i].block);
 170046         }
 170047     }
 170048   // 
 170049   // The block is new for the cache: must find
 170050   // the older and replace it.
 170051   // 
 170052   for (i = 0; i < BLK_CACHE_SIZE; i++)
 170053     {
 170054       if (blk_table[i].age == BLK_CACHE_MAX_AGE)
 170055         {
 170056           for (j = 0; j < BLK_CACHE_SIZE; j++)
 170057             {
 170058               if (blk_table[j].age < BLK_CACHE_MAX_AGE)
 170059                 {
 170060                   blk_table[j].age++;
 170061                 }
 170062             }
 170063           blk_table[i].age = 0;
 170064           blk_table[i].device = device;
 170065           blk_table[i].n = n;
 170066           memcpy (blk_table[i].block, block,
 170067                   (size_t) BLK_SIZE);
 170068           // 
 170069           return (&blk_table[i].block);
 170070         }
 170071     }
 170072   // 
 170073   // It should never happen to fail.
 170074   // 
 170075   return (NULL);
 170076 }

94.2.6   kernel/blk/blk_public.c

Si veda la sezione 93.3.

 180001 #include <kernel/blk.h>
 180002 //----------------------------------------------------------
 180003 blk_cache_t blk_table[BLK_CACHE_SIZE];

94.3   os32: «kernel/dev.h»

Si veda la sezione 93.4.

 190001 #ifndef _KERNEL_DEV_H
 190002 #define _KERNEL_DEV_H 1
 190003 //----------------------------------------------------------
 190004 #include <sys/os32.h>
 190005 #include <sys/types.h>
 190006 #include <kernel/driver/ata.h>
 190007 //----------------------------------------------------------
 190008 #define DEV_READ                0
 190009 #define DEV_WRITE               1
 190010 ssize_t dev_io (pid_t pid, dev_t device, int rw,
 190011                 off_t offset, void *buffer,
 190012                 size_t size, int *eof);
 190013 //----------------------------------------------------------
 190014 // The following functions are used only by `dev_io()'.
 190015 //----------------------------------------------------------
 190016 ssize_t dev_dm (pid_t pid, dev_t device, int rw,
 190017                 off_t offset, void *buffer,
 190018                 size_t size, int *eof);
 190019 ssize_t dev_ata (pid_t pid, dev_t device, int rw,
 190020                  off_t offset, void *buffer,
 190021                  size_t size, int *eof);
 190022 ssize_t dev_mem (pid_t pid, dev_t device, int rw,
 190023                  off_t offset, void *buffer,
 190024                  size_t size, int *eof);
 190025 ssize_t dev_tty (pid_t pid, dev_t device, int rw,
 190026                  off_t offset, void *buffer,
 190027                  size_t size, int *eof);
 190028 ssize_t dev_kmem (pid_t pid, dev_t device, int rw,
 190029                   off_t offset, void *buffer,
 190030                   size_t size, int *eof);
 190031 //----------------------------------------------------------
 190032 #endif

94.3.1   kernel/dev/dev_ata.c

Si veda la sezione 93.4.3.

 200001 #include <sys/os32.h>
 200002 #include <kernel/dev.h>
 200003 #include <kernel/blk.h>
 200004 #include <kernel/driver/ata.h>
 200005 #include <kernel/lib_k.h>
 200006 #include <kernel/dm.h>
 200007 #include <sys/types.h>
 200008 #include <ctype.h>
 200009 #include <errno.h>
 200010 //----------------------------------------------------------
 200011 ssize_t
 200012 dev_ata (pid_t pid, dev_t device, int rw, off_t offset,
 200013          void *buffer, size_t size, int *eof)
 200014 {
 200015   ssize_t m;
 200016   ssize_t n = 0;
 200017   unsigned char *data_buffer = buffer;
 200018   unsigned int n_blk;
 200019   int i;
 200020   int j = 0;
 200021   char *block;
 200022   // 
 200023   // Read the first block.
 200024   // 
 200025   n_blk = offset / BLK_SIZE;
 200026   i = offset % BLK_SIZE;
 200027   // 
 200028   block = blk_ata (device, DEV_READ, n_blk, NULL);
 200029   if (block == NULL)
 200030     {
 200031       errset (errno);
 200032       return ((ssize_t) - 1);
 200033     }
 200034   // 
 200035   // Read or write.
 200036   // 
 200037   if (rw == DEV_READ)
 200038     {
 200039       while (size)
 200040         {
 200041           for (;
 200042                i < BLK_SIZE && size > 0;
 200043                i++, j++, n++, size--, offset++)
 200044             {
 200045               data_buffer[j] = block[i];
 200046             }
 200047           if (size)
 200048             {
 200049               n_blk = offset / BLK_SIZE;
 200050               i = offset % BLK_SIZE;
 200051               block = blk_ata (device, DEV_READ, n_blk,
 200052                                NULL);
 200053               if (block == NULL)
 200054                 {
 200055                   errset (errno);
 200056                   return (n);   // Up to the last
 200057                   // block read.
 200058                 }
 200059             }
 200060         }
 200061     }
 200062   else
 200063     {
 200064       // 
 200065       // Write.
 200066       // 
 200067       while (size)
 200068         {
 200069           // 
 200070           // The last block was written, so update
 200071           // the counter `m'.
 200072           // 
 200073           m = n;
 200074           // 
 200075           for (;
 200076                i < BLK_SIZE && size > 0;
 200077                i++, j++, n++, size--, offset++)
 200078             {
 200079               block[i] = data_buffer[j];
 200080             }
 200081           block = blk_ata (device, DEV_WRITE, n_blk, block);
 200082           if (block == NULL)
 200083             {
 200084               errset (errno);
 200085               return (m);       // Up to the last
 200086               // block written.
 200087             }
 200088           if (size)
 200089             {
 200090               n_blk = offset / BLK_SIZE;
 200091               i = offset % BLK_SIZE;
 200092               block = blk_ata (device, DEV_READ, n_blk,
 200093                                NULL);
 200094               if (block == NULL)
 200095                 {
 200096                   errset (errno);
 200097                   return (m);   // Up to the last
 200098                   // block written.
 200099                 }
 200100             }
 200101         }
 200102     }
 200103   // 
 200104   // Everything was right, so `n' is valid for both
 200105   // read or write.
 200106   // 
 200107   return (n);
 200108 }

94.3.2   kernel/dev/dev_dm.c

Si veda la sezione 93.4.2.

 210001 #include <sys/os32.h>
 210002 #include <kernel/dev.h>
 210003 #include <kernel/driver/ata.h>
 210004 #include <kernel/lib_k.h>
 210005 #include <kernel/dm.h>
 210006 #include <sys/types.h>
 210007 #include <ctype.h>
 210008 #include <errno.h>
 210009 //----------------------------------------------------------
 210010 ssize_t
 210011 dev_dm (pid_t pid, dev_t device, int rw, off_t offset,
 210012         void *buffer, size_t size, int *eof)
 210013 {
 210014   int dev_minor = minor (device);
 210015   int p = dev_minor & 0x000F;
 210016   int d = ((dev_minor & 0x00F0) >> 4);
 210017   // 
 210018   // If it is a partition, must verify if such
 210019   // partition exists.
 210020   // 
 210021   if (p)
 210022     {
 210023       // 
 210024       // It is a partition.
 210025       // 
 210026       if (dm_table[d].part[p].type == PART_TYPE_NONE)
 210027         {
 210028           errset (ENODEV);
 210029           return ((ssize_t) - 1);
 210030         }
 210031     }
 210032   // 
 210033   // Shift the offset to the start of partition.
 210034   // 
 210035   offset += (dm_table[d].part[p].start);
 210036   // 
 210037   // Call the right hardware driver.
 210038   // 
 210039   switch (dm_table[d].type)
 210040     {
 210041     case DM_TYPE_ATA:
 210042       return (dev_ata
 210043               (pid, device, rw, offset, buffer, size, eof));
 210044       break;
 210045     default:
 210046       errset (ENODEV);
 210047       return ((ssize_t) - 1);
 210048     }
 210049 }

94.3.3   kernel/dev/dev_io.c

Si veda la sezione 93.4.1.

 220001 #include <sys/os32.h>
 220002 #include <kernel/dev.h>
 220003 #include <sys/types.h>
 220004 #include <errno.h>
 220005 #include <kernel/ibm_i386.h>
 220006 #include <kernel/proc.h>
 220007 #include <string.h>
 220008 #include <signal.h>
 220009 #include <kernel/lib_k.h>
 220010 #include <ctype.h>
 220011 #include <kernel/driver/tty.h>
 220012 //----------------------------------------------------------
 220013 ssize_t
 220014 dev_io (pid_t pid, dev_t device, int rw, off_t offset,
 220015         void *buffer, size_t size, int *eof)
 220016 {
 220017   int dev_major = major (device);
 220018   if (rw != DEV_READ && rw != DEV_WRITE)
 220019     {
 220020       errset (EIO);
 220021       return (-1);
 220022     }
 220023   switch (dev_major)
 220024     {
 220025     case DEV_MEM_MAJOR:
 220026       return (dev_mem
 220027               (pid, device, rw, offset, buffer, size, eof));
 220028     case DEV_TTY_MAJOR:
 220029       return (dev_tty
 220030               (pid, device, rw, offset, buffer, size, eof));
 220031     case DEV_CONSOLE_MAJOR:
 220032       return (dev_tty
 220033               (pid, device, rw, offset, buffer, size, eof));
 220034     case DEV_DM_MAJOR:
 220035       return (dev_dm
 220036               (pid, device, rw, offset, buffer, size, eof));
 220037     case DEV_KMEM_MAJOR:
 220038       return (dev_kmem
 220039               (pid, device, rw, offset, buffer, size, eof));
 220040     default:
 220041       errset (ENODEV);
 220042       return (-1);
 220043     }
 220044 }

94.3.4   kernel/dev/dev_kmem.c

Si veda la sezione 93.4.4.

 230001 #include <sys/os32.h>
 230002 #include <kernel/dev.h>
 230003 #include <sys/types.h>
 230004 #include <errno.h>
 230005 #include <kernel/memory.h>
 230006 #include <kernel/proc.h>
 230007 #include <kernel/net/arp.h>
 230008 #include <kernel/net/route.h>
 230009 #include <kernel/net.h>
 230010 #include <string.h>
 230011 #include <signal.h>
 230012 #include <ctype.h>
 230013 //----------------------------------------------------------
 230014 ssize_t
 230015 dev_kmem (pid_t pid, dev_t device, int rw,
 230016           off_t offset, void *buffer, size_t size, int *eof)
 230017 {
 230018   inode_t *inode;
 230019   sb_t *sb;
 230020   file_t *file;
 230021   void *start;
 230022   char *m;
 230023   // 
 230024   // Only read is allowed.
 230025   // 
 230026   if (rw != DEV_READ)
 230027     {
 230028       errset (EIO);     // I/O error.
 230029       return ((ssize_t) - 1);
 230030     }
 230031   // 
 230032   // Only positive offset is allowed.
 230033   // 
 230034   if (offset < 0)
 230035     {
 230036       errset (EIO);     // I/O error.
 230037       return ((ssize_t) - 1);
 230038     }
 230039   // 
 230040   // Read is selected (and is the only access
 230041   // allowed).
 230042   // 
 230043   switch (device)
 230044     {
 230045     case DEV_KMEM_PS:
 230046       // 
 230047       // Verify if the selected slot can be read.
 230048       // 
 230049       if (offset >= PROCESS_MAX)
 230050         {
 230051           errset (EIO); // I/O error.
 230052           return ((ssize_t) - 1);
 230053         }
 230054       // 
 230055       // Correct the size to be read.
 230056       // 
 230057       if (sizeof (proc_t) < size)
 230058         {
 230059           size = sizeof (proc_t);
 230060         }
 230061       // 
 230062       // Get the pointer to the selected slot.
 230063       // 
 230064       start = proc_reference ((pid_t) offset);
 230065       break;
 230066     case DEV_KMEM_MMP:
 230067       // 
 230068       // Correct the size to be read.
 230069       // 
 230070       if (offset >= (MEM_MAX_BLOCKS / 8))
 230071         {
 230072           *eof = 1;
 230073           errset (EIO); // I/O error.
 230074           return ((ssize_t) - 1);
 230075         }
 230076       // 
 230077       // Reduce size if necessary.
 230078       // 
 230079       if ((offset + size) > (MEM_MAX_BLOCKS / 8))
 230080         {
 230081           size = ((MEM_MAX_BLOCKS / 8) - offset);
 230082         }
 230083       // 
 230084       // Get the pointer to the map: offset is not
 230085       // taken
 230086       // into consideration.
 230087       // 
 230088       m = (char *) mb_reference ();
 230089       // 
 230090       start = &m[offset];
 230091       // 
 230092       break;
 230093     case DEV_KMEM_SB:
 230094       // 
 230095       // Verify if the selected slot can be read.
 230096       // 
 230097       if (offset >= SB_MAX_SLOTS)
 230098         {
 230099           errset (EIO); // I/O error.
 230100           return ((ssize_t) - 1);
 230101         }
 230102       // 
 230103       // Get a reference to the super block table.
 230104       // 
 230105       sb = sb_reference (0);
 230106       // 
 230107       // Correct the size to be read.
 230108       // 
 230109       if (sizeof (sb_t) < size)
 230110         {
 230111           size = sizeof (sb_t);
 230112         }
 230113       // 
 230114       // Get the pointer to the selected super block
 230115       // slot.
 230116       // 
 230117       start = &sb[offset];
 230118       break;
 230119     case DEV_KMEM_INODE:
 230120       // 
 230121       // Verify if the selected slot can be read.
 230122       // 
 230123       if (offset >= INODE_MAX_SLOTS)
 230124         {
 230125           errset (EIO); // I/O error.
 230126           return ((ssize_t) - 1);
 230127         }
 230128       // 
 230129       // Get a reference to the inode table.
 230130       // 
 230131       inode = inode_reference (0, 0);
 230132       // 
 230133       // Correct the size to be read.
 230134       // 
 230135       if (sizeof (inode_t) < size)
 230136         {
 230137           size = sizeof (inode_t);
 230138         }
 230139       // 
 230140       // Get the pointer to the selected inode slot.
 230141       // 
 230142       start = &inode[offset];
 230143       break;
 230144     case DEV_KMEM_FILE:
 230145       // 
 230146       // Verify if the selected slot can be read.
 230147       // 
 230148       if (offset >= FILE_MAX_SLOTS)
 230149         {
 230150           errset (EIO); // I/O error.
 230151           return ((ssize_t) - 1);
 230152         }
 230153       // 
 230154       // Get a reference to the file table.
 230155       // 
 230156       file = file_reference (0);
 230157       // 
 230158       // Correct the size to be read.
 230159       // 
 230160       if (sizeof (file_t) < size)
 230161         {
 230162           size = sizeof (file_t);
 230163         }
 230164       // 
 230165       // Get the pointer to the selected inode slot.
 230166       // 
 230167       start = &file[offset];
 230168       break;
 230169     case DEV_KMEM_ARP:
 230170       // 
 230171       // Verify if the selected slot can be read.
 230172       // 
 230173       if (offset >= ARP_MAX_ITEMS)
 230174         {
 230175           errset (EIO); // I/O error.
 230176           return ((ssize_t) - 1);
 230177         }
 230178       // 
 230179       // Correct the size to be read.
 230180       // 
 230181       if (sizeof (arp_t) < size)
 230182         {
 230183           size = sizeof (arp_t);
 230184         }
 230185       // 
 230186       // Get the pointer to the selected ARP item.
 230187       // 
 230188       start = &arp_table[offset];
 230189       break;
 230190     case DEV_KMEM_NET:
 230191       // 
 230192       // Verify if the selected slot can be read.
 230193       // 
 230194       if (offset >= NET_MAX_DEVICES)
 230195         {
 230196           errset (EIO); // I/O error.
 230197           return ((ssize_t) - 1);
 230198         }
 230199       // 
 230200       // Correct the size to be read.
 230201       // 
 230202       if (sizeof (net_t) < size)
 230203         {
 230204           size = sizeof (net_t);
 230205         }
 230206       // 
 230207       // Get the pointer to the selected NET table
 230208       // item.
 230209       // 
 230210       start = &net_table[offset];
 230211       break;
 230212     case DEV_KMEM_ROUTE:
 230213       // 
 230214       // Verify if the selected slot can be read.
 230215       // 
 230216       if (offset >= ROUTE_MAX_ROUTES)
 230217         {
 230218           errset (EIO); // I/O error.
 230219           return ((ssize_t) - 1);
 230220         }
 230221       // 
 230222       // Correct the size to be read.
 230223       // 
 230224       if (sizeof (route_t) < size)
 230225         {
 230226           size = sizeof (route_t);
 230227         }
 230228       // 
 230229       // Get the pointer to the selected NET table
 230230       // item.
 230231       // 
 230232       start = &route_table[offset];
 230233       break;
 230234     default:
 230235       errset (ENODEV);  // No such device.
 230236       return ((ssize_t) - 1);
 230237     }
 230238   // 
 230239   // At this point, data is ready to be copied to the
 230240   // buffer.
 230241   // 
 230242   memcpy (buffer, start, size);
 230243   // 
 230244   // Return size read.
 230245   // 
 230246   return (size);
 230247 }

94.3.5   kernel/dev/dev_mem.c

Si veda la sezione 93.4.5.

 240001 #include <sys/os32.h>
 240002 #include <kernel/dev.h>
 240003 #include <sys/types.h>
 240004 #include <errno.h>
 240005 #include <kernel/memory.h>
 240006 #include <kernel/ibm_i386.h>
 240007 #include <kernel/proc.h>
 240008 #include <string.h>
 240009 #include <signal.h>
 240010 #include <kernel/lib_k.h>
 240011 #include <ctype.h>
 240012 //----------------------------------------------------------
 240013 ssize_t
 240014 dev_mem (pid_t pid, dev_t device, int rw, off_t offset,
 240015          void *buffer, size_t size, int *eof)
 240016 {
 240017   uint8_t *buffer08 = (uint8_t *) buffer;
 240018   uint16_t *buffer16 = (uint16_t *) buffer;
 240019   ssize_t n;
 240020 
 240021   if (device == DEV_MEM)        // DEV_MEM
 240022     {
 240023       if (rw == DEV_READ)
 240024         {
 240025           memcpy (buffer, (void *) (int) offset, size);
 240026           n = size;
 240027         }
 240028       else
 240029         {
 240030           if (pid == 0)
 240031             {
 240032               memcpy ((void *) (int) offset, buffer, size);
 240033               n = size;
 240034             }
 240035           else
 240036             {
 240037               k_printf
 240038                 ("kernel alert: only the kernel "
 240039                  "can write the memory where it "
 240040                  "likes!\n");
 240041               errset (EIO);     // I/O error.
 240042               return ((ssize_t) - 1);
 240043             }
 240044         }
 240045     }
 240046   else if (device == DEV_NULL)  // DEV_NULL
 240047     {
 240048       n = 0;
 240049     }
 240050   else if (device == DEV_ZERO)  // DEV_ZERO
 240051     {
 240052       if (rw == DEV_READ)
 240053         {
 240054           for (n = 0; n < size; n++)
 240055             {
 240056               buffer08[n] = 0;
 240057             }
 240058         }
 240059       else
 240060         {
 240061           n = 0;
 240062         }
 240063     }
 240064   else if (device == DEV_PORT)  // DEV_PORT
 240065     {
 240066       if (rw == DEV_READ)
 240067         {
 240068           if (size == 1)
 240069             {
 240070               buffer08[0] = in_8 (offset);
 240071               n = 1;
 240072             }
 240073           else if (size == 2)
 240074             {
 240075               buffer16[0] = in_16 (offset);
 240076               n = 2;
 240077             }
 240078           else
 240079             {
 240080               n = 0;
 240081             }
 240082         }
 240083       else
 240084         {
 240085           if (size == 1)
 240086             {
 240087               out_8 (offset, buffer08[0]);
 240088             }
 240089           else if (size == 2)
 240090             {
 240091               out_16 (offset, buffer16[0]);
 240092               n = 2;
 240093             }
 240094           else
 240095             {
 240096               n = 0;
 240097             }
 240098         }
 240099     }
 240100   else
 240101     {
 240102       errset (ENODEV);
 240103       return ((ssize_t) - 1);
 240104     }
 240105   return (n);
 240106 }

94.3.6   kernel/dev/dev_tty.c

Si veda la sezione 93.4.6.

 250001 #include <sys/os32.h>
 250002 #include <kernel/dev.h>
 250003 #include <sys/types.h>
 250004 #include <errno.h>
 250005 #include <kernel/memory.h>
 250006 #include <kernel/ibm_i386.h>
 250007 #include <kernel/proc.h>
 250008 #include <string.h>
 250009 #include <signal.h>
 250010 #include <kernel/lib_k.h>
 250011 #include <ctype.h>
 250012 #include <kernel/driver/tty.h>
 250013 //----------------------------------------------------------
 250014 ssize_t
 250015 dev_tty (pid_t pid, dev_t device, int rw, off_t offset,
 250016          void *buffer, size_t size, int *eof)
 250017 {
 250018   uint8_t *buffer08 = (uint8_t *) buffer;
 250019   ssize_t n;
 250020   proc_t *ps;
 250021   int key;
 250022   // 
 250023   // Get process. Variable `ps' will be `NULL' if the
 250024   // process ID is
 250025   // not valid.
 250026   // 
 250027   ps = proc_reference (pid);
 250028   // 
 250029   // Convert `DEV_TTY' with the controlling terminal
 250030   // for the process.
 250031   // 
 250032   if (device == DEV_TTY)
 250033     {
 250034       device = ps->device_tty;
 250035       // 
 250036       // As a last resort, use the generic
 250037       // `DEV_CONSOLE'.
 250038       // 
 250039       if (device == DEV_UNDEFINED || device == DEV_TTY)
 250040         {
 250041           device = DEV_CONSOLE;
 250042         }
 250043     }
 250044   // 
 250045   // Convert `DEV_CONSOLE' to the currently active
 250046   // console.
 250047   // 
 250048   if (device == DEV_CONSOLE)
 250049     {
 250050       device = tty_console ((dev_t) 0);
 250051       // 
 250052       // As a last resort, use the first console:
 250053       // `DEV_CONSOLE0'.
 250054       // 
 250055       if (device == DEV_UNDEFINED || device == DEV_TTY)
 250056         {
 250057           device = DEV_CONSOLE0;
 250058         }
 250059     }
 250060   // 
 250061   // Read or write.
 250062   // 
 250063   if (rw == DEV_READ)
 250064     {
 250065       for (n = 0; n < size; n++)
 250066         {
 250067           key = tty_read (device);
 250068           if (key == 0 && n == 0)
 250069             {
 250070               // 
 250071               // A single line contains zero: this is
 250072               // made by a VEOF
 250073               // character (^d), that is, the input is 
 250074               // closed,
 250075               // so return zero read and EOF.
 250076               // 
 250077               *eof = 1;
 250078               return (0);
 250079             }
 250080           else if (key == -1 && n == 0)
 250081             {
 250082               // 
 250083               // At the moment, there is just nothing
 250084               // to read.
 250085               // 
 250086               errset (EAGAIN);
 250087               return (-1);
 250088             }
 250089           else if (key == -1 && n > 0)
 250090             {
 250091               // 
 250092               // Finished to read.
 250093               // 
 250094               break;
 250095             }
 250096           else
 250097             {
 250098               buffer08[n] = key;
 250099             }
 250100         }
 250101     }
 250102   else
 250103     {
 250104       for (n = 0; n < size; n++)
 250105         {
 250106           tty_write (device, (int) buffer08[n]);
 250107         }
 250108     }
 250109   return (n);
 250110 }

94.4   os32: «kernel/dm.h»

Si veda la sezione 93.5.

 260001 #ifndef _KERNEL_DM_H
 260002 #define _KERNEL_DM_H    1
 260003 //----------------------------------------------------------
 260004 #include <stdint.h>
 260005 #include <sys/types.h>
 260006 #include <kernel/part.h>
 260007 //----------------------------------------------------------
 260008 #define DM_MAX_DEVICES   4
 260009 #define DM_TYPE_NONE     0
 260010 #define DM_TYPE_ATA      1
 260011 //
 260012 typedef struct
 260013 {
 260014   int type;
 260015   void *table;
 260016   struct
 260017   {
 260018     off_t start;
 260019     size_t size;
 260020     uint8_t type;
 260021   } part[PART_MAX + 1];
 260022 } dm_t;
 260023 //
 260024 extern dm_t dm_table[DM_MAX_DEVICES];
 260025 //----------------------------------------------------------
 260026 void dm_init (void);
 260027 //----------------------------------------------------------
 260028 #endif

94.4.1   kernel/dm/dm_init.c

Si veda la sezione 93.5.

 270001 #include <kernel/dm.h>
 270002 #include <kernel/part.h>
 270003 #include <kernel/driver/ata.h>
 270004 #include <kernel/lib_k.h>
 270005 #include <stdint.h>
 270006 #include <errno.h>
 270007 //----------------------------------------------------------
 270008 void
 270009 dm_init (void)
 270010 {
 270011   int d;
 270012   int a;
 270013   int p;
 270014   ata_sector_t sector_buffer;
 270015   part_t *part;
 270016   int status;
 270017   // 
 270018   // Reset the data-memory table.
 270019   // 
 270020   for (d = 0; d < DM_MAX_DEVICES; d++)
 270021     {
 270022       dm_table[d].type = DM_TYPE_NONE;
 270023       dm_table[d].table = NULL;
 270024       dm_table[d].part[0].start = 0;
 270025       dm_table[d].part[0].size = 0;
 270026       dm_table[d].part[0].type = PART_TYPE_NO_PART;
 270027       for (p = 0; p < PART_MAX; p++)
 270028         {
 270029           dm_table[d].part[p + 1].start = 0;
 270030           dm_table[d].part[p + 1].size = 0;
 270031           dm_table[d].part[p + 1].type = PART_TYPE_NONE;
 270032         }
 270033     }
 270034   // 
 270035   // Reset data-memory index.
 270036   // 
 270037   d = 0;
 270038   // 
 270039   // Init ATA devices.
 270040   // 
 270041   ata_init ();
 270042   // 
 270043   // Assign ATA devices to the first data-memory
 270044   // items.
 270045   // 
 270046   for (a = 0; a < ATA_MAX_DEVICES; a++)
 270047     {
 270048       if (ata_table[a].present == 0)
 270049         {
 270050           // 
 270051           // Current data-memory device will be
 270052           // used for the next ATA device, if any.
 270053           // 
 270054           continue;
 270055         }
 270056       // 
 270057       // Show something.
 270058       // 
 270059       k_printf ("[%s] ATA drive=%i total sectors=%i\n",
 270060                 __func__, a, (int) ata_table[d].sectors);
 270061       // 
 270062       dm_table[d].type = DM_TYPE_ATA;
 270063       dm_table[d].table = &ata_table[a];
 270064       dm_table[d].part[0].start = 0;
 270065       dm_table[d].part[0].size = ata_table[a].sectors;
 270066       dm_table[d].part[0].type = PART_TYPE_NO_PART;
 270067       // 
 270068       // Read partitions.
 270069       // 
 270070       status = ata_read_sector (a, 0, &sector_buffer);
 270071       // 
 270072       if (status)
 270073         {
 270074           errset (errno);
 270075           k_perror (NULL);
 270076         }
 270077       else
 270078         {
 270079           part =
 270080             (((void *) &sector_buffer) + PART_TABLE_OFF);
 270081           // 
 270082           for (p = 0; p < PART_MAX; p++)
 270083             {
 270084               // 
 270085               dm_table[d].part[p + 1].start =
 270086                 part->l_start * ATA_SECTOR_SIZE;
 270087               dm_table[d].part[p + 1].size =
 270088                 part->size * ATA_SECTOR_SIZE;
 270089               dm_table[d].part[p + 1].type = part->type;
 270090               // 
 270091               // Show info.
 270092               // 
 270093               if (part->type != 0)
 270094                 {
 270095                   k_printf ("[%s] partition type=%02x "
 270096                             "start sector=%i "
 270097                             "total sectors=%i\n",
 270098                             __func__, (int) part->type,
 270099                             (int) part->l_start,
 270100                             (int) part->size);
 270101                 }
 270102               // 
 270103               part++;
 270104             }
 270105         }
 270106       // 
 270107       // Next data-memory device.
 270108       // 
 270109       d++;
 270110     }
 270111 }

94.4.2   kernel/dm/dm_public.c

Si veda la sezione 93.5.

 280001 #include <kernel/dm.h>
 280002 //----------------------------------------------------------
 280003 dm_t dm_table[DM_MAX_DEVICES];

94.4.3   kernel/driver/ata.h

Si veda la sezione 93.2.

 290001 #ifndef _KERNEL_DRIVER_ATA_H
 290002 #define _KERNEL_DRIVER_ATA_H    1
 290003 //----------------------------------------------------------
 290004 #include <stdint.h>
 290005 #include <sys/types.h>
 290006 #include <time.h>
 290007 //----------------------------------------------------------
 290008 //
 290009 // I/O ports, used to access ATA bus registers. These
 290010 // I/O ports are different for every ATA bus.
 290011 //
 290012 #define ATA0_DATA          0x1F0        // r/w
 290013 #define ATA0_FEATURE       0x1F1        // -/w
 290014 #define ATA0_ERROR         0x1F1        // r/-
 290015 #define ATA0_COUNT         0x1F2        // r/w
 290016 #define ATA0_LOW           0x1F3        // r/w
 290017 #define ATA0_MID           0x1F4        // r/w
 290018 #define ATA0_HIGH          0x1F5        // r/w
 290019 #define ATA0_DEVICE        0x1F6        // r/w
 290020 #define ATA0_COMMAND       0x1F7        // -/w
 290021 #define ATA0_STATUS        0x1F7        // r/- regular
 290022                                         // status
 290023 #define ATA0_CONTROL       0x3F6        // -/w
 290024 #define ATA0_ALTERNATE     0x3F6        // w/-
 290025                                         // alternate
 290026                                         // status
 290027 //
 290028 #define ATA1_DATA          0x170        // r/w
 290029 #define ATA1_FEATURE       0x171        // -/w
 290030 #define ATA1_ERROR         0x171        // r/-
 290031 #define ATA1_COUNT         0x172        // r/w
 290032 #define ATA1_LOW           0x173        // r/w
 290033 #define ATA1_MID           0x174        // r/w
 290034 #define ATA1_HIGH          0x175        // r/w
 290035 #define ATA1_DEVICE        0x176        // r/w
 290036 #define ATA1_COMMAND       0x177        // -/w
 290037 #define ATA1_STATUS        0x177        // r/- regular
 290038                                         // status
 290039 #define ATA1_CONTROL       0x376        // -/w
 290040 #define ATA1_ALTERNATE     0x376        // w/-
 290041                                         // alternate
 290042                                         // status
 290043 //
 290044 #define ATA2_DATA          0x1E8        // r/w
 290045 #define ATA2_FEATURE       0x1E9        // -/w
 290046 #define ATA2_ERROR         0x1E9        // r/-
 290047 #define ATA2_COUNT         0x1EA        // r/w
 290048 #define ATA2_LOW           0x1EB        // r/w
 290049 #define ATA2_MID           0x1EC        // r/w
 290050 #define ATA2_HIGH          0x1ED        // r/w
 290051 #define ATA2_DEVICE        0x1EE        // r/w
 290052 #define ATA2_COMMAND       0x1EF        // -/w
 290053 #define ATA2_STATUS        0x1EF        // r/- regular
 290054                                         // status
 290055 #define ATA2_CONTROL       0x3E6        // -/w
 290056 #define ATA2_ALTERNATE     0x3E6        // w/-
 290057                                         // alternate
 290058                                         // status
 290059 //
 290060 #define ATA3_DATA          0x168        // r/w
 290061 #define ATA3_FEATURE       0x169        // -/w
 290062 #define ATA3_ERROR         0x169        // r/-
 290063 #define ATA3_COUNT         0x16A        // r/w
 290064 #define ATA3_LOW           0x16B        // r/w
 290065 #define ATA3_MID           0x16C        // r/w
 290066 #define ATA3_HIGH          0x16D        // r/w
 290067 #define ATA3_DEVICE        0x16E        // r/w
 290068 #define ATA3_COMMAND       0x16F        // -/w
 290069 #define ATA3_STATUS        0x16F        // r/- regular
 290070                                         // status
 290071 #define ATA3_CONTROL       0x366        // -/w
 290072 #define ATA3_ALTERNATE     0x366        // w/-
 290073                                         // alternate
 290074                                         // status
 290075 //
 290076 // Status register flags (regular or alternate).
 290077 //
 290078 #define ATA_STATUS_BSY            0x80  // Busy
 290079 #define ATA_STATUS_DRDY           0x40  // Ready
 290080 #define ATA_STATUS_DF             0x20  // Drive Fault
 290081 #define ATA_STATUS_DRQ            0x08  // Data
 290082                                         // request
 290083 #define ATA_STATUS_ERR            0x01  // Error
 290084 //
 290085 // Values to put to the device register
 290086 //
 290087 #define ATA_DEVICE_CHS          0x00
 290088 #define ATA_DEVICE_LBA          0x40
 290089 #define ATA_DEVICE_MASTER       0x00
 290090 #define ATA_DEVICE_SLAVE        0x10
 290091 //
 290092 // Values to put to the command register
 290093 //
 290094 #define ATA_COMMAND_IDENTIFY_DEVICE      0xEC
 290095 #define ATA_COMMAND_READ_SECTORS         0x20
 290096 #define ATA_COMMAND_WRITE_SECTORS        0x30
 290097 #define ATA_COMMAND_FLUSH_CACHE          0xE7
 290098 //
 290099 // Values to put to the control register
 290100 // (device control register).
 290101 //
 290102 #define ATA_CONTROL_HOB        0x80
 290103 #define ATA_CONTROL_SRST       0x04     // Software
 290104                                         // reset.
 290105 #define ATA_CONTROL_NIEN       0x01     // No
 290106                                         // Interrupt
 290107                                         // enabled.
 290108 //
 290109 //
 290110 //
 290111 #define ATA_MAX_DEVICES        8        // Fixed.
 290112 #define ATA_SECTOR_SIZE        512      // Fixed.
 290113 #define ATA_TIMEOUT  \
 290114     ((clock_t) (CLOCKS_PER_SEC * 1))    // 1 s
 290115 #define ATA_TIMEOUT_FLUSH \
 290116     ((clock_t) (CLOCKS_PER_SEC * 10))   // 10 s
 290117 //
 290118 //
 290119 //
 290120 typedef struct
 290121 {
 290122   unsigned short r_data;
 290123   unsigned short r_feature;
 290124   unsigned short r_error;
 290125   unsigned short r_count;
 290126   unsigned short r_low;
 290127   unsigned short r_mid;
 290128   unsigned short r_high;
 290129   unsigned short r_device;
 290130   unsigned short r_command;
 290131   unsigned short r_status;
 290132   unsigned short r_control;
 290133   unsigned short r_alternate;
 290134   unsigned char bus;
 290135   unsigned char target;
 290136   unsigned char present;
 290137   uint16_t id[ATA_SECTOR_SIZE / 2];
 290138   unsigned int sectors;
 290139 } ata_t;
 290140 //
 290141 typedef struct
 290142 {
 290143   char byte[ATA_SECTOR_SIZE];
 290144 } ata_sector_t;
 290145 //
 290146 extern ata_t ata_table[ATA_MAX_DEVICES];
 290147 //----------------------------------------------------------
 290148 void ata_init (void);
 290149 void ata_reset (int drive);
 290150 int ata_valid (int drive);
 290151 //----------------------------------------------------------
 290152 int ata_cmd_identify_device (int drive, void *buffer);
 290153 int ata_cmd_read_sectors (int drive,
 290154                           unsigned int sector,
 290155                           unsigned char count,
 290156                           void *buffer);
 290157 int ata_cmd_write_sectors (int drive,
 290158                            unsigned int sector,
 290159                            unsigned char count,
 290160                            void *buffer);
 290161 int ata_device (int drive, unsigned int sector);
 290162 //----------------------------------------------------------
 290163 int ata_rdy (int drive, clock_t timeout);
 290164 int ata_drq (int drive, clock_t timeout);
 290165 int ata_lba28 (int drive, unsigned int sector,
 290166                unsigned char count);
 290167 //----------------------------------------------------------
 290168 #define ata_read_sector(drive, sector, buffer)  \
 290169     (ata_cmd_read_sectors ((int) drive, \
 290170      (unsigned int) sector, \
 290171      (unsigned char) 1, (void *) buffer))
 290172 //
 290173 #define ata_write_sector(drive, sector, buffer)  \
 290174     (ata_cmd_write_sectors ((int) drive, \
 290175      (unsigned int) sector, \
 290176      (unsigned char) 1, (void *) buffer))
 290177 //----------------------------------------------------------
 290178 #endif

94.4.4   kernel/driver/ata/ata_cmd_identify_device.c

Si veda la sezione 93.2.

 300001 #include <kernel/driver/ata.h>
 300002 #include <kernel/lib_k.h>
 300003 #include <kernel/ibm_i386.h>
 300004 #include <stdint.h>
 300005 #include <errno.h>
 300006 //----------------------------------------------------------
 300007 int
 300008 ata_cmd_identify_device (int drive, void *buffer)
 300009 {
 300010   unsigned char status;
 300011   int s;
 300012   int i;
 300013   uint16_t *id = buffer;
 300014   // 
 300015   // Register `device'.
 300016   // 
 300017   s = ata_device (drive, 0);
 300018   if (s < 0)
 300019     {
 300020       errset (errno);
 300021       return (-1);
 300022     }
 300023   // 
 300024   // Send `command'
 300025   // 
 300026   out_8 (ata_table[drive].r_command,
 300027          ATA_COMMAND_IDENTIFY_DEVICE);
 300028   // 
 300029   // Read the regular status port.
 300030   // 
 300031   status = in_8 (ata_table[drive].r_status);
 300032   // 
 300033   // If the status is zero, there is no drive.
 300034   // 
 300035   if (status == 0)
 300036     {
 300037       // 
 300038       // Clear the `id[]' array and return.
 300039       // 
 300040       for (i = 0; i < (ATA_SECTOR_SIZE / 2); i++)
 300041         {
 300042           id[i] = 0;
 300043         }
 300044       return (0);
 300045     }
 300046   // 
 300047   // Wait for the drive ready to send data.
 300048   // 
 300049   s = ata_drq (drive, ATA_TIMEOUT);
 300050   if (s < 0)
 300051     {
 300052       errset (errno);
 300053       return (-1);
 300054     }
 300055   // 
 300056   // Read data.
 300057   // 
 300058   for (i = 0; i < (ATA_SECTOR_SIZE / 2); i++)
 300059     {
 300060       id[i] = in_16 (ata_table[drive].r_data);
 300061     }
 300062   // 
 300063   // Return.
 300064   // 
 300065   return (0);
 300066 }

94.4.5   kernel/driver/ata/ata_cmd_read_sectors.c

Si veda la sezione 93.2.

 310001 #include <kernel/driver/ata.h>
 310002 #include <kernel/lib_k.h>
 310003 #include <kernel/ibm_i386.h>
 310004 #include <stdint.h>
 310005 #include <errno.h>
 310006 //----------------------------------------------------------
 310007 int
 310008 ata_cmd_read_sectors (int drive, unsigned int sector,
 310009                       unsigned char count, void *buffer)
 310010 {
 310011   int s;
 310012   int i;
 310013   int c;
 310014   uint16_t *destination = buffer;
 310015   // 
 310016   // Set LBA 28 parameters.
 310017   // 
 310018   s = ata_lba28 (drive, sector, count);
 310019   if (s < 0)
 310020     {
 310021       errset (errno);
 310022       return (-1);
 310023     }
 310024   // 
 310025   // Send `command'
 310026   // 
 310027   out_8 (ata_table[drive].r_command,
 310028          ATA_COMMAND_READ_SECTORS);
 310029   // 
 310030   // Parameter `count' equal to zero means 256
 310031   // sectors.
 310032   // 
 310033   if (count == 0)
 310034     {
 310035       c = 256;
 310036     }
 310037   else
 310038     {
 310039       c = count;
 310040     }
 310041   // 
 310042   // Read `c' sectors.
 310043   // 
 310044   for (; c > 0; c--)
 310045     {
 310046       s = ata_drq (drive, ATA_TIMEOUT);
 310047       if (s < 0)
 310048         {
 310049           errset (errno);
 310050           return (-1);
 310051         }
 310052       // 
 310053       // Read sector.
 310054       // 
 310055       for (i = 0; i < (ATA_SECTOR_SIZE / 2); i++)
 310056         {
 310057           destination[i] = in_16 (ata_table[drive].r_data);
 310058         }
 310059     }
 310060   // 
 310061   // Wait that the device returns ready.
 310062   // 
 310063   s = ata_rdy (drive, ATA_TIMEOUT);
 310064   if (s < 0)
 310065     {
 310066       errset (errno);
 310067       return (-1);
 310068     }
 310069   // 
 310070   // Return.
 310071   // 
 310072   return (0);
 310073 }

94.4.6   kernel/driver/ata/ata_cmd_write_sectors.c

Si veda la sezione 93.2.

 320001 #include <kernel/driver/ata.h>
 320002 #include <kernel/lib_k.h>
 320003 #include <kernel/ibm_i386.h>
 320004 #include <stdint.h>
 320005 #include <errno.h>
 320006 //----------------------------------------------------------
 320007 int
 320008 ata_cmd_write_sectors (int drive, unsigned int sector,
 320009                        unsigned char count, void *buffer)
 320010 {
 320011   int s;
 320012   int i;
 320013   int c;
 320014   uint16_t *source = buffer;
 320015   // 
 320016   // Set LBA 28 parameters.
 320017   // 
 320018   s = ata_lba28 (drive, sector, count);
 320019   if (s < 0)
 320020     {
 320021       errset (errno);
 320022       return (-1);
 320023     }
 320024   // 
 320025   // Send `command'
 320026   // 
 320027   out_8 (ata_table[drive].r_command,
 320028          ATA_COMMAND_WRITE_SECTORS);
 320029   // 
 320030   // Parameter `count' equal to zero means 256
 320031   // sectors.
 320032   // 
 320033   if (count == 0)
 320034     {
 320035       c = 256;
 320036     }
 320037   else
 320038     {
 320039       c = count;
 320040     }
 320041   // 
 320042   // Read `c' sectors.
 320043   // 
 320044   for (; c > 0; c--)
 320045     {
 320046       s = ata_drq (drive, ATA_TIMEOUT);
 320047       if (s < 0)
 320048         {
 320049           errset (errno);
 320050           return (-1);
 320051         }
 320052       // 
 320053       // Write sector.
 320054       // 
 320055       for (i = 0; i < (ATA_SECTOR_SIZE / 2); i++)
 320056         {
 320057           out_16 (ata_table[drive].r_data, source[i]);
 320058         }
 320059     }
 320060   // 
 320061   // Wait that the device returns ready.
 320062   // 
 320063   s = ata_rdy (drive, ATA_TIMEOUT);
 320064   if (s < 0)
 320065     {
 320066       errset (errno);
 320067       return (-1);
 320068     }
 320069   // 
 320070   // Now flush cache.
 320071   // 
 320072   out_8 (ata_table[drive].r_command,
 320073          ATA_COMMAND_FLUSH_CACHE);
 320074   // 
 320075   // Then wait that the device returns ready.
 320076   // 
 320077   s = ata_rdy (drive, ATA_TIMEOUT_FLUSH);
 320078   if (s < 0)
 320079     {
 320080       errset (errno);
 320081       return (-1);
 320082     }
 320083   // 
 320084   // Return.
 320085   // 
 320086   return (0);
 320087 }

94.4.7   kernel/driver/ata/ata_device.c

Si veda la sezione 93.2.

 330001 #include <kernel/driver/ata.h>
 330002 #include <kernel/lib_s.h>
 330003 #include <kernel/ibm_i386.h>
 330004 #include <stdint.h>
 330005 #include <errno.h>
 330006 //----------------------------------------------------------
 330007 int
 330008 ata_device (int drive, unsigned int sector)
 330009 {
 330010   unsigned char device;
 330011   int s;
 330012   // 
 330013   // Verify `drive' argument.
 330014   // 
 330015   s = ata_valid (drive);
 330016   if (s < 0)
 330017     {
 330018       errset (EINVAL);
 330019       return (-1);
 330020     }
 330021   // 
 330022   // Start building the `device' register.
 330023   // 
 330024   device = 0;
 330025   // 
 330026   // The access will be LBA: no CHS at all here!
 330027   // 
 330028   device |= ATA_DEVICE_LBA;
 330029   // 
 330030   // Set the device number, relative to the bus.
 330031   // 
 330032   device |= ata_table[drive].target;
 330033   // 
 330034   // Put the highest four bits of the sector number,
 330035   // that can use at most 28 bits.
 330036   // 
 330037   device |= ((sector & 0x0F000000) >> 24);
 330038   // 
 330039   // Must select the new drive.
 330040   // 
 330041   out_8 (ata_table[drive].r_device, device);
 330042   // 
 330043   // Wait for selected drive ready.
 330044   // 
 330045   s = ata_rdy (drive, ATA_TIMEOUT);
 330046   if (s < 0)
 330047     {
 330048       errset (errno);
 330049       return (-1);
 330050     }
 330051   // 
 330052   // Ok.
 330053   // 
 330054   return (0);
 330055 }

94.4.8   kernel/driver/ata/ata_drq.c

Si veda la sezione 93.2.

 340001 #include <kernel/driver/ata.h>
 340002 #include <kernel/lib_s.h>
 340003 #include <kernel/ibm_i386.h>
 340004 #include <stdint.h>
 340005 #include <errno.h>
 340006 //----------------------------------------------------------
 340007 int
 340008 ata_drq (int drive, clock_t timeout)
 340009 {
 340010   clock_t time_start;
 340011   clock_t time_now;
 340012   clock_t time_elapsed;
 340013   int status;
 340014   // 
 340015   // The timeout value must be at least two.
 340016   // 
 340017   if (timeout < 2)
 340018     {
 340019       timeout = 2;
 340020     }
 340021   // 
 340022   // Get the status register.
 340023   // 
 340024   time_elapsed = 0;
 340025   time_start = s_clock ((pid_t) 0);
 340026   while (time_elapsed < timeout)
 340027     {
 340028       time_now = s_clock ((pid_t) 0);
 340029       time_elapsed = time_now - time_start;
 340030       // 
 340031       status = in_8 (ata_table[drive].r_status);
 340032       // 
 340033       // Is it BSY?
 340034       // 
 340035       if (status & ATA_STATUS_BSY)
 340036         {
 340037           // 
 340038           // Read the status again.
 340039           // 
 340040           continue;
 340041         }
 340042       // 
 340043       // No more busy, but check for errors.
 340044       // 
 340045       if (status & ATA_STATUS_DF)
 340046         {
 340047           k_printf ("[%s] ERROR: drive %i fault\n",
 340048                     __func__, drive);
 340049           ata_reset (drive);
 340050           errset (E_HARDWARE_FAULT);
 340051           return (-1);
 340052         }
 340053       // 
 340054       if (status & ATA_STATUS_ERR)
 340055         {
 340056           k_printf ("[%s] ERROR: drive %i error\n",
 340057                     __func__, drive);
 340058           ata_reset (drive);
 340059           errset (E_DRIVER_FAULT);
 340060           return (-1);
 340061         }
 340062       // 
 340063       // Now check for the DRQ.
 340064       // 
 340065       if (status & ATA_STATUS_DRQ)
 340066         {
 340067           // 
 340068           // Ok.
 340069           // 
 340070           return (0);
 340071         }
 340072     }
 340073   // 
 340074   // Sorry: time out!
 340075   // 
 340076   k_printf ("[%s] ERROR: drive %i timeout\n", __func__,
 340077             drive);
 340078   errset (ETIME);
 340079   return (-1);
 340080 }

94.4.9   kernel/driver/ata/ata_init.c

Si veda la sezione 93.2.

 350001 #include <kernel/driver/ata.h>
 350002 #include <kernel/lib_k.h>
 350003 #include <kernel/ibm_i386.h>
 350004 #include <stdint.h>
 350005 #include <errno.h>
 350006 //----------------------------------------------------------
 350007 void
 350008 ata_init (void)
 350009 {
 350010   unsigned char status;
 350011   int s;
 350012   int d;
 350013   // 
 350014   // Set bus numbers and I/O ports for each possible
 350015   // drive.
 350016   // I/O ports are related to the bus, so every couple 
 350017   // of
 350018   // drive has the same ports.
 350019   // 
 350020   if (ATA_MAX_DEVICES > 0)
 350021     {
 350022       ata_table[0].bus = 0;
 350023       ata_table[0].r_data = ATA0_DATA;
 350024       ata_table[0].r_feature = ATA0_FEATURE;
 350025       ata_table[0].r_error = ATA0_ERROR;
 350026       ata_table[0].r_count = ATA0_COUNT;
 350027       ata_table[0].r_low = ATA0_LOW;
 350028       ata_table[0].r_mid = ATA0_MID;
 350029       ata_table[0].r_high = ATA0_HIGH;
 350030       ata_table[0].r_device = ATA0_DEVICE;
 350031       ata_table[0].r_command = ATA0_COMMAND;
 350032       ata_table[0].r_status = ATA0_STATUS;
 350033       ata_table[0].r_control = ATA0_CONTROL;
 350034       ata_table[0].r_alternate = ATA0_ALTERNATE;
 350035       ata_table[0].target = ATA_DEVICE_MASTER;
 350036       // 
 350037       ata_table[1].bus = 0;
 350038       ata_table[1].r_data = ATA0_DATA;
 350039       ata_table[1].r_feature = ATA0_FEATURE;
 350040       ata_table[1].r_error = ATA0_ERROR;
 350041       ata_table[1].r_count = ATA0_COUNT;
 350042       ata_table[1].r_low = ATA0_LOW;
 350043       ata_table[1].r_mid = ATA0_MID;
 350044       ata_table[1].r_high = ATA0_HIGH;
 350045       ata_table[1].r_device = ATA0_DEVICE;
 350046       ata_table[1].r_command = ATA0_COMMAND;
 350047       ata_table[1].r_status = ATA0_STATUS;
 350048       ata_table[1].r_control = ATA0_CONTROL;
 350049       ata_table[1].r_alternate = ATA0_ALTERNATE;
 350050       ata_table[1].target = ATA_DEVICE_SLAVE;
 350051     }
 350052   // 
 350053   if (ATA_MAX_DEVICES > 2)
 350054     {
 350055       ata_table[2].bus = 1;
 350056       ata_table[2].r_data = ATA1_DATA;
 350057       ata_table[2].r_feature = ATA1_FEATURE;
 350058       ata_table[2].r_error = ATA1_ERROR;
 350059       ata_table[2].r_count = ATA1_COUNT;
 350060       ata_table[2].r_low = ATA1_LOW;
 350061       ata_table[2].r_mid = ATA1_MID;
 350062       ata_table[2].r_high = ATA1_HIGH;
 350063       ata_table[2].r_device = ATA1_DEVICE;
 350064       ata_table[2].r_command = ATA1_COMMAND;
 350065       ata_table[2].r_status = ATA1_STATUS;
 350066       ata_table[2].r_control = ATA1_CONTROL;
 350067       ata_table[2].r_alternate = ATA1_ALTERNATE;
 350068       ata_table[2].target = ATA_DEVICE_MASTER;
 350069       // 
 350070       ata_table[3].bus = 1;
 350071       ata_table[3].r_data = ATA1_DATA;
 350072       ata_table[3].r_feature = ATA1_FEATURE;
 350073       ata_table[3].r_error = ATA1_ERROR;
 350074       ata_table[3].r_count = ATA1_COUNT;
 350075       ata_table[3].r_low = ATA1_LOW;
 350076       ata_table[3].r_mid = ATA1_MID;
 350077       ata_table[3].r_high = ATA1_HIGH;
 350078       ata_table[3].r_device = ATA1_DEVICE;
 350079       ata_table[3].r_command = ATA1_COMMAND;
 350080       ata_table[3].r_status = ATA1_STATUS;
 350081       ata_table[3].r_control = ATA1_CONTROL;
 350082       ata_table[3].r_alternate = ATA1_ALTERNATE;
 350083       ata_table[3].target = ATA_DEVICE_SLAVE;
 350084     }
 350085   // 
 350086   if (ATA_MAX_DEVICES > 4)
 350087     {
 350088       ata_table[4].bus = 2;
 350089       ata_table[4].r_data = ATA2_DATA;
 350090       ata_table[4].r_feature = ATA2_FEATURE;
 350091       ata_table[4].r_error = ATA2_ERROR;
 350092       ata_table[4].r_count = ATA2_COUNT;
 350093       ata_table[4].r_low = ATA2_LOW;
 350094       ata_table[4].r_mid = ATA2_MID;
 350095       ata_table[4].r_high = ATA2_HIGH;
 350096       ata_table[4].r_device = ATA2_DEVICE;
 350097       ata_table[4].r_command = ATA2_COMMAND;
 350098       ata_table[4].r_status = ATA2_STATUS;
 350099       ata_table[4].r_control = ATA2_CONTROL;
 350100       ata_table[4].r_alternate = ATA2_ALTERNATE;
 350101       ata_table[4].target = ATA_DEVICE_MASTER;
 350102       // 
 350103       ata_table[5].bus = 2;
 350104       ata_table[5].r_data = ATA2_DATA;
 350105       ata_table[5].r_feature = ATA2_FEATURE;
 350106       ata_table[5].r_error = ATA2_ERROR;
 350107       ata_table[5].r_count = ATA2_COUNT;
 350108       ata_table[5].r_low = ATA2_LOW;
 350109       ata_table[5].r_mid = ATA2_MID;
 350110       ata_table[5].r_high = ATA2_HIGH;
 350111       ata_table[5].r_device = ATA2_DEVICE;
 350112       ata_table[5].r_command = ATA2_COMMAND;
 350113       ata_table[5].r_status = ATA2_STATUS;
 350114       ata_table[5].r_control = ATA2_CONTROL;
 350115       ata_table[5].r_alternate = ATA2_ALTERNATE;
 350116       ata_table[5].target = ATA_DEVICE_SLAVE;
 350117     }
 350118   // 
 350119   if (ATA_MAX_DEVICES > 6)
 350120     {
 350121       ata_table[6].bus = 3;
 350122       ata_table[6].r_data = ATA3_DATA;
 350123       ata_table[6].r_feature = ATA3_FEATURE;
 350124       ata_table[6].r_error = ATA3_ERROR;
 350125       ata_table[6].r_count = ATA3_COUNT;
 350126       ata_table[6].r_low = ATA3_LOW;
 350127       ata_table[6].r_mid = ATA3_MID;
 350128       ata_table[6].r_high = ATA3_HIGH;
 350129       ata_table[6].r_device = ATA3_DEVICE;
 350130       ata_table[6].r_command = ATA3_COMMAND;
 350131       ata_table[6].r_status = ATA3_STATUS;
 350132       ata_table[6].r_control = ATA3_CONTROL;
 350133       ata_table[6].r_alternate = ATA3_ALTERNATE;
 350134       ata_table[6].target = ATA_DEVICE_MASTER;
 350135       // 
 350136       ata_table[7].bus = 3;
 350137       ata_table[7].r_data = ATA3_DATA;
 350138       ata_table[7].r_feature = ATA3_FEATURE;
 350139       ata_table[7].r_error = ATA3_ERROR;
 350140       ata_table[7].r_count = ATA3_COUNT;
 350141       ata_table[7].r_low = ATA3_LOW;
 350142       ata_table[7].r_mid = ATA3_MID;
 350143       ata_table[7].r_high = ATA3_HIGH;
 350144       ata_table[7].r_device = ATA3_DEVICE;
 350145       ata_table[7].r_command = ATA3_COMMAND;
 350146       ata_table[7].r_status = ATA3_STATUS;
 350147       ata_table[7].r_control = ATA3_CONTROL;
 350148       ata_table[7].r_alternate = ATA3_ALTERNATE;
 350149       ata_table[7].target = ATA_DEVICE_SLAVE;
 350150     }
 350151   // 
 350152   // Scan and eliminate buses with no drive at all.
 350153   // 
 350154   for (d = 0; d < ATA_MAX_DEVICES; d += 2)
 350155     {
 350156       status = in_8 (ata_table[d].r_status);
 350157       if (status == 0xFF)
 350158         {
 350159           ata_table[d].present = 0;
 350160           ata_table[d + 1].present = 0;
 350161         }
 350162       else
 350163         {
 350164           ata_table[d].present = 1;
 350165           ata_table[d + 1].present = 1;
 350166         }
 350167     }
 350168   // 
 350169   // Identify drives.
 350170   // 
 350171   for (d = 0; d < ATA_MAX_DEVICES; d++)
 350172     {
 350173       if (ata_table[d].present == 0)
 350174         {
 350175           continue;
 350176         }
 350177       // 
 350178       // Register `device'.
 350179       // 
 350180       s = ata_device (d, 0);
 350181       if (s < 0)
 350182         {
 350183           errset (errno);
 350184           k_perror (NULL);
 350185           ata_table[d].present = 0;
 350186           continue;
 350187         }
 350188       // 
 350189       // Send command `IDENTIFY DEVICE'
 350190       // 
 350191       s =
 350192         ata_cmd_identify_device (d, &(ata_table[d].id[0]));
 350193       if (s < 0)
 350194         {
 350195           ata_table[d].present = 0;
 350196           continue;
 350197         }
 350198       // 
 350199       // Verify again if the drive is present: the
 350200       // function might have found that it does not
 350201       // exist.
 350202       // 
 350203       if (ata_table[d].present == 0)
 350204         {
 350205           continue;
 350206         }
 350207       // 
 350208       // Find total sectors (for 28 bit LBA access).
 350209       // It is written
 350210       // inside the integer formed by `identity[60]'
 350211       // and
 350212       // `identity[61]', considering it in little
 350213       // endian mode.
 350214       // It is taken the pointer to `identity[60]',
 350215       // transformed
 350216       // into a pointer to a 32 bit integer, and then
 350217       // dereferenced
 350218       // again.
 350219       // 
 350220       ata_table[d].sectors
 350221         = *((uint32_t *) & (ata_table[d].id[60]));
 350222       // 
 350223       // Check if the size value is right.
 350224       // 
 350225       if (ata_table[d].sectors == 0)
 350226         {
 350227           ata_table[d].present = 0;
 350228         }
 350229       else
 350230         {
 350231           // 
 350232           // Show info.
 350233           // 
 350234           k_printf ("[%s] ATA drive %i size %i Kib\n",
 350235                     __func__, d, ata_table[d].sectors / 2);
 350236         }
 350237     }
 350238 }

94.4.10   kernel/driver/ata/ata_lba28.c

Si veda la sezione 93.2.

 360001 #include <kernel/driver/ata.h>
 360002 #include <kernel/lib_s.h>
 360003 #include <kernel/ibm_i386.h>
 360004 #include <stdint.h>
 360005 #include <errno.h>
 360006 //----------------------------------------------------------
 360007 int
 360008 ata_lba28 (int drive, unsigned int sector,
 360009            unsigned char count)
 360010 {
 360011   int s;
 360012   unsigned char low;
 360013   unsigned char mid;
 360014   unsigned char high;
 360015   // 
 360016   // Register `device'.
 360017   // 
 360018   s = ata_device (drive, sector);
 360019   if (s < 0)
 360020     {
 360021       k_perror (NULL);
 360022 
 360023       errset (errno);
 360024       return (-1);
 360025     }
 360026   // 
 360027   // Register `control', to set nIEN.
 360028   // 
 360029   out_8 (ata_table[drive].r_control, ATA_CONTROL_NIEN);
 360030   // 
 360031   // Register `feature'. not used.
 360032   // 
 360033   out_8 (ata_table[drive].r_feature, 0);
 360034   // 
 360035   // Register `count'
 360036   // 
 360037   out_8 (ata_table[drive].r_count, count);
 360038   // 
 360039   // Registers `low', `mid', `high'.
 360040   // 
 360041   low = (sector & 0x000000FF);
 360042   mid = ((sector & 0x0000FF00) >> 8);
 360043   high = ((sector & 0x00FF0000) >> 16);
 360044   // 
 360045   out_8 (ata_table[drive].r_low, low);
 360046   out_8 (ata_table[drive].r_mid, mid);
 360047   out_8 (ata_table[drive].r_high, high);
 360048   // 
 360049   // Ok.
 360050   // 
 360051   return (0);
 360052 }

94.4.11   kernel/driver/ata/ata_public.c

Si veda la sezione 93.2.

 370001 #include <kernel/driver/ata.h>
 370002 //----------------------------------------------------------
 370003 ata_t ata_table[ATA_MAX_DEVICES];
 370004 //----------------------------------------------------------

94.4.12   kernel/driver/ata/ata_rdy.c

Si veda la sezione 93.2.

 380001 #include <kernel/driver/ata.h>
 380002 #include <kernel/lib_s.h>
 380003 #include <kernel/ibm_i386.h>
 380004 #include <stdint.h>
 380005 #include <errno.h>
 380006 //----------------------------------------------------------
 380007 int
 380008 ata_rdy (int drive, clock_t timeout)
 380009 {
 380010   clock_t time_start;
 380011   clock_t time_now;
 380012   clock_t time_elapsed;
 380013   unsigned char status;
 380014   // 
 380015   // The timeout value must be at least two.
 380016   // 
 380017   if (timeout < 2)
 380018     {
 380019       timeout = 2;
 380020     }
 380021   // 
 380022   // Get the status register.
 380023   // 
 380024   time_elapsed = 0;
 380025   time_start = s_clock ((pid_t) 0);
 380026   while (time_elapsed < timeout)
 380027     {
 380028       time_now = s_clock ((pid_t) 0);
 380029       time_elapsed = time_now - time_start;
 380030       // 
 380031       status = in_8 (ata_table[drive].r_status);
 380032       // 
 380033       // Is it BSY?
 380034       // 
 380035       if (status & ATA_STATUS_BSY)
 380036         {
 380037           // 
 380038           // Read the status again.
 380039           // 
 380040           continue;
 380041         }
 380042       // 
 380043       // No more busy, but check for errors.
 380044       // 
 380045       if (status & ATA_STATUS_DF)
 380046         {
 380047           k_printf ("[%s] ERROR: drive %i fault\n",
 380048                     __func__, drive);
 380049           ata_reset (drive);
 380050           errset (E_HARDWARE_FAULT);
 380051           return (-1);
 380052         }
 380053       // 
 380054       if (status & ATA_STATUS_ERR)
 380055         {
 380056           k_printf ("[%s] ERROR: drive %i error\n",
 380057                     __func__, drive);
 380058           ata_reset (drive);
 380059           errset (E_DRIVER_FAULT);
 380060           return (-1);
 380061         }
 380062       // 
 380063       // Otherwise: ok.
 380064       // 
 380065       return (0);
 380066     }
 380067   // 
 380068   // Sorry: time out!
 380069   // 
 380070   k_printf ("[%s] ERROR: drive %i timeout\n", __func__,
 380071             drive);
 380072   errset (ETIME);
 380073   return (-1);
 380074 }

94.4.13   kernel/driver/ata/ata_reset.c

Si veda la sezione 93.2.

 390001 #include <kernel/driver/ata.h>
 390002 #include <kernel/lib_s.h>
 390003 #include <kernel/ibm_i386.h>
 390004 #include <stdint.h>
 390005 #include <errno.h>
 390006 //----------------------------------------------------------
 390007 void
 390008 ata_reset (int drive)
 390009 {
 390010   out_8 (ata_table[drive].r_control, ATA_CONTROL_SRST);
 390011   out_8 (ata_table[drive].r_control, 0);
 390012 }

94.4.14   kernel/driver/ata/ata_valid.c

Si veda la sezione 93.2.

 400001 #include <kernel/driver/ata.h>
 400002 #include <errno.h>
 400003 //----------------------------------------------------------
 400004 int
 400005 ata_valid (int drive)
 400006 {
 400007   // 
 400008   // Verify if `drive' argument is possible.
 400009   // 
 400010   if (drive < 0 || drive >= ATA_MAX_DEVICES)
 400011     {
 400012       errset (EINVAL);
 400013       return (-1);
 400014     }
 400015   // 
 400016   // Verify if `drive' is present at the moment.
 400017   // 
 400018   if (ata_table[drive].present == 0)
 400019     {
 400020       errset (E_NO_MEDIUM);
 400021       return (-1);
 400022     }
 400023   // 
 400024   // OK.
 400025   // 
 400026   return (0);
 400027 }

94.4.15   kernel/driver/kbd.h

Si veda la sezione 93.10.

 410001 #ifndef _KERNEL_DRIVER_KBD_H
 410002 #define _KERNEL_DRIVER_KBD_H     1
 410003 //----------------------------------------------------------
 410004 #include <stdbool.h>
 410005 //----------------------------------------------------------
 410006 //
 410007 // Keyboard status.
 410008 //
 410009 typedef struct
 410010 {
 410011   bool shift;
 410012   bool shift_lock;
 410013   bool ctrl;
 410014   bool alt;
 410015   bool echo;
 410016   unsigned char key;
 410017   unsigned char map1[128];
 410018   unsigned char map2[128];
 410019 } kbd_t;
 410020 //
 410021 extern kbd_t kbd;
 410022 //----------------------------------------------------------
 410023 void kbd_load (void);
 410024 void kbd_isr (void);
 410025 //----------------------------------------------------------
 410026 #endif

94.4.16   kernel/driver/kbd/kbd_isr.c

Si veda la sezione 93.10.

 420001 #include <kernel/driver/kbd.h>
 420002 #include <kernel/ibm_i386.h>
 420003 //----------------------------------------------------------
 420004 void
 420005 kbd_isr (void)
 420006 {
 420007   // 
 420008   // Get a character from the keyboard channel.
 420009   // 
 420010   unsigned char scancode = (int) in_8 (0x60);
 420011   // 
 420012   // Check for [Shift], [Shift-Lock], [Ctrl] and [Alt] 
 420013   // keys.
 420014   // 
 420015   switch (scancode)
 420016     {
 420017     case 0x2A:
 420018       kbd.shift = 1;
 420019       break;
 420020     case 0x36:
 420021       kbd.shift = 1;
 420022       break;
 420023     case 0xAA:
 420024       kbd.shift = 0;
 420025       break;
 420026     case 0xB6:
 420027       kbd.shift = 0;
 420028       break;
 420029     case 0x1D:
 420030       kbd.ctrl = 1;
 420031       break;
 420032     case 0x9D:
 420033       kbd.ctrl = 0;
 420034       break;
 420035     case 0x38:
 420036       kbd.alt = 1;
 420037       break;
 420038     case 0xB8:
 420039       kbd.alt = 0;
 420040       break;
 420041     case 0x3A:
 420042       kbd.shift_lock = !kbd.shift_lock;
 420043       break;
 420044     }
 420045   // 
 420046   // Check for usual keys, but only if `kbd.key' is
 420047   // currently empty.
 420048   // 
 420049   if (scancode <= 127 && kbd.ctrl && kbd.key == 0)
 420050     {
 420051       // 
 420052       // Something was pressed, combined with [Ctrl].
 420053       // 
 420054       switch (kbd.map1[scancode])
 420055         {
 420056         case 'a':
 420057           kbd.key = 0x01;
 420058           break;        // SOH
 420059         case 'b':
 420060           kbd.key = 0x02;
 420061           break;        // STX
 420062         case 'c':
 420063           kbd.key = 0x03;
 420064           break;        // ETX
 420065         case 'd':
 420066           kbd.key = 0x04;
 420067           break;        // EOT
 420068         case 'e':
 420069           kbd.key = 0x05;
 420070           break;        // ENQ
 420071         case 'f':
 420072           kbd.key = 0x06;
 420073           break;        // ACK
 420074         case 'g':
 420075           kbd.key = 0x07;
 420076           break;        // BEL
 420077         case 'h':
 420078           kbd.key = 0x08;
 420079           break;        // BS
 420080         case 'i':
 420081           kbd.key = 0x09;
 420082           break;        // HT
 420083         case 'j':
 420084           kbd.key = 0x0A;
 420085           break;        // LF
 420086         case 'k':
 420087           kbd.key = 0x0B;
 420088           break;        // VT
 420089         case 'l':
 420090           kbd.key = 0x0C;
 420091           break;        // FF
 420092         case 'm':
 420093           kbd.key = 0x0D;
 420094           break;        // CR
 420095         case 'n':
 420096           kbd.key = 0x0E;
 420097           break;        // SO
 420098         case 'o':
 420099           kbd.key = 0x0F;
 420100           break;        // SI
 420101         case 'p':
 420102           kbd.key = 0x10;
 420103           break;        // DLE
 420104         case 'q':
 420105           kbd.key = 0x11;
 420106           break;        // DC1
 420107         case 'r':
 420108           kbd.key = 0x12;
 420109           break;        // DC2
 420110         case 's':
 420111           kbd.key = 0x13;
 420112           break;        // DC3
 420113         case 't':
 420114           kbd.key = 0x14;
 420115           break;        // DC4
 420116         case 'u':
 420117           kbd.key = 0x15;
 420118           break;        // NAK
 420119         case 'v':
 420120           kbd.key = 0x16;
 420121           break;        // SYN
 420122         case 'w':
 420123           kbd.key = 0x17;
 420124           break;        // ETB
 420125         case 'x':
 420126           kbd.key = 0x18;
 420127           break;        // CAN
 420128         case 'y':
 420129           kbd.key = 0x19;
 420130           break;        // EM
 420131         case 'z':
 420132           kbd.key = 0x1A;
 420133           break;        // SUB
 420134         case '[':
 420135           kbd.key = 0x1B;
 420136           break;        // ESC
 420137         case '\\':
 420138           kbd.key = 0x1C;
 420139           break;        // FS
 420140         case ']':
 420141           kbd.key = 0x1D;
 420142           break;        // GS
 420143         case '^':
 420144           kbd.key = 0x1E;
 420145           break;        // RS
 420146         case '_':
 420147           kbd.key = 0x1F;
 420148           break;        // US
 420149         }
 420150     }
 420151   else if (scancode <= 127 && kbd.key == 0
 420152            && kbd.map1[scancode] != 0)
 420153     {
 420154       // 
 420155       // Something was pressed, but no [Ctrl] is
 420156       // there.
 420157       // 
 420158       if (kbd.shift || kbd.shift_lock)
 420159         {
 420160           kbd.key = kbd.map2[scancode];
 420161         }
 420162       else
 420163         {
 420164           kbd.key = kbd.map1[scancode];
 420165         }
 420166     }
 420167 }

94.4.17   kernel/driver/kbd/kbd_load.c

Si veda la sezione 93.10.

 430001 #include <kernel/driver/kbd.h>
 430002 //----------------------------------------------------------
 430003 void
 430004 kbd_load (void)
 430005 {
 430006   int i;
 430007   // 
 430008   // Reset the map.
 430009   // 
 430010   for (i = 0; i <= 127; i++)
 430011     {
 430012       kbd.map1[i] = 0;
 430013       kbd.map2[i] = 0;
 430014     }
 430015   // 
 430016   // Association for an italian map, but only with
 430017   // ASCII characters
 430018   // (there are no accented letters).
 430019   // 
 430020   kbd.map1[1] = 27;
 430021   kbd.map2[1] = 27;     // ESC
 430022   kbd.map1[2] = '1';
 430023   kbd.map2[2] = '!';
 430024   kbd.map1[3] = '2';
 430025   kbd.map2[3] = '"';
 430026   kbd.map1[4] = '3';
 430027   kbd.map2[4] = 'L';    // 3, £
 430028   kbd.map1[5] = '4';
 430029   kbd.map2[5] = '$';
 430030   kbd.map1[6] = '5';
 430031   kbd.map2[6] = '%';
 430032   kbd.map1[7] = '6';
 430033   kbd.map2[7] = '&';
 430034   kbd.map1[8] = '7';
 430035   kbd.map2[8] = '/';
 430036   kbd.map1[9] = '8';
 430037   kbd.map2[9] = '(';
 430038   kbd.map1[10] = '9';
 430039   kbd.map2[10] = ')';
 430040   kbd.map1[11] = '0';
 430041   kbd.map2[11] = '=';
 430042   kbd.map1[12] = '\'';
 430043   kbd.map2[12] = '?';
 430044   kbd.map1[13] = 'i';
 430045   kbd.map2[13] = '^';   // ì, ^
 430046   kbd.map1[14] = '\b';
 430047   kbd.map2[14] = '\b';  // Backspace
 430048   kbd.map1[15] = '\t';
 430049   kbd.map2[15] = '\t';
 430050   kbd.map1[16] = 'q';
 430051   kbd.map2[16] = 'Q';
 430052   kbd.map1[17] = 'w';
 430053   kbd.map2[17] = 'W';
 430054   kbd.map1[18] = 'e';
 430055   kbd.map2[18] = 'E';
 430056   kbd.map1[19] = 'r';
 430057   kbd.map2[19] = 'R';
 430058   kbd.map1[20] = 't';
 430059   kbd.map2[20] = 'T';
 430060   kbd.map1[21] = 'y';
 430061   kbd.map2[21] = 'Y';
 430062   kbd.map1[22] = 'u';
 430063   kbd.map2[22] = 'U';
 430064   kbd.map1[23] = 'i';
 430065   kbd.map2[23] = 'I';
 430066   kbd.map1[24] = 'o';
 430067   kbd.map2[24] = 'O';
 430068   kbd.map1[25] = 'p';
 430069   kbd.map2[25] = 'P';
 430070   kbd.map1[26] = '[';
 430071   kbd.map2[26] = '{';   // è, é
 430072   kbd.map1[27] = ']';
 430073   kbd.map2[27] = '}';   // +, *
 430074   kbd.map1[28] = '\n';
 430075   kbd.map2[28] = '\n';  // Enter
 430076   kbd.map1[30] = 'a';
 430077   kbd.map2[30] = 'A';
 430078   kbd.map1[31] = 's';
 430079   kbd.map2[31] = 'S';
 430080   kbd.map1[32] = 'd';
 430081   kbd.map2[32] = 'D';
 430082   kbd.map1[33] = 'f';
 430083   kbd.map2[33] = 'F';
 430084   kbd.map1[34] = 'g';
 430085   kbd.map2[34] = 'G';
 430086   kbd.map1[35] = 'h';
 430087   kbd.map2[35] = 'H';
 430088   kbd.map1[36] = 'j';
 430089   kbd.map2[36] = 'J';
 430090   kbd.map1[37] = 'k';
 430091   kbd.map2[37] = 'K';
 430092   kbd.map1[38] = 'l';
 430093   kbd.map2[38] = 'L';
 430094   kbd.map1[39] = '@';
 430095   kbd.map2[39] = '@';   // ò, ç
 430096   kbd.map1[40] = '#';
 430097   kbd.map2[40] = '#';   // à, °
 430098   kbd.map1[41] = '\\';
 430099   kbd.map2[41] = '|';
 430100   kbd.map1[43] = 'u';
 430101   kbd.map2[43] = 'U';   // ù, §
 430102   kbd.map1[44] = 'z';
 430103   kbd.map2[44] = 'Z';
 430104   kbd.map1[45] = 'x';
 430105   kbd.map2[45] = 'X';
 430106   kbd.map1[46] = 'c';
 430107   kbd.map2[46] = 'C';
 430108   kbd.map1[47] = 'v';
 430109   kbd.map2[47] = 'V';
 430110   kbd.map1[48] = 'b';
 430111   kbd.map2[48] = 'B';
 430112   kbd.map1[49] = 'n';
 430113   kbd.map2[49] = 'N';
 430114   kbd.map1[50] = 'm';
 430115   kbd.map2[50] = 'M';
 430116   kbd.map1[51] = ',';
 430117   kbd.map2[51] = ';';
 430118   kbd.map1[52] = '.';
 430119   kbd.map2[52] = ':';
 430120   kbd.map1[53] = '-';
 430121   kbd.map2[53] = '_';
 430122   kbd.map1[56] = '<';
 430123   kbd.map2[56] = '>';
 430124   kbd.map1[57] = ' ';
 430125   kbd.map2[57] = ' ';
 430126   // 
 430127   kbd.map1[55] = '*';
 430128   kbd.map2[55] = '*';
 430129   kbd.map1[71] = '7';
 430130   kbd.map2[71] = '7';
 430131   kbd.map1[72] = '8';
 430132   kbd.map2[72] = '8';
 430133   kbd.map1[73] = '9';
 430134   kbd.map2[73] = '9';
 430135   kbd.map1[74] = '-';
 430136   kbd.map2[74] = '-';
 430137   kbd.map1[75] = '4';
 430138   kbd.map2[75] = '4';
 430139   kbd.map1[76] = '5';
 430140   kbd.map2[76] = '5';
 430141   kbd.map1[77] = '6';
 430142   kbd.map2[77] = '6';
 430143   kbd.map1[78] = '+';
 430144   kbd.map2[78] = '+';
 430145   kbd.map1[79] = '1';
 430146   kbd.map2[79] = '1';
 430147   kbd.map1[80] = '2';
 430148   kbd.map2[80] = '2';
 430149   kbd.map1[81] = '3';
 430150   kbd.map2[81] = '3';
 430151   kbd.map1[82] = '0';
 430152   kbd.map2[82] = '0';
 430153   kbd.map1[83] = '.';
 430154   kbd.map2[83] = '.';
 430155   kbd.map1[92] = '/';
 430156   kbd.map2[92] = '/';
 430157   kbd.map1[96] = '\n';
 430158   kbd.map2[96] = '\n';  // Enter
 430159 }

94.4.18   kernel/driver/kbd/kbd_public.c

Si veda la sezione 93.10.

 440001 #include <kernel/driver/kbd.h>
 440002 //----------------------------------------------------------
 440003 kbd_t kbd;

94.4.19   kernel/driver/nic/ne2k.h

Si veda la sezione 93.16.

 450001 #ifndef _KERNEL_DRIVER_NIC_NE2K_H
 450002 #define _KERNEL_DRIVER_NIC_NE2K_H    1
 450003 //----------------------------------------------------------
 450004 #include <stdint.h>
 450005 #include <sys/types.h>
 450006 #include <unistd.h>
 450007 #include <time.h>
 450008 //----------------------------------------------------------
 450009 //
 450010 // Command register, available on all pages.
 450011 //
 450012 #define NE2K_CR         0x00    // rw
 450013 //
 450014 // Page 0 registers
 450015 //
 450016 #define NE2K_CLDA0      0x01    // r-
 450017 #define NE2K_PSTART     0x01    // -w
 450018 #define NE2K_CLDA1      0x02    // r-
 450019 #define NE2K_PSTOP      0x02    // -w
 450020 #define NE2K_BNRY       0x03    // rw
 450021 #define NE2K_TSR        0x04    // r-
 450022 #define NE2K_TPSR       0x04    // -w
 450023 #define NE2K_NCR        0x05    // r-
 450024 #define NE2K_TBCR0      0x05    // -w
 450025 #define NE2K_FIFO       0x06    // r-
 450026 #define NE2K_TBCR1      0x06    // -w
 450027 #define NE2K_ISR        0x07    // rw
 450028 #define NE2K_CRDA0      0x08    // r-
 450029 #define NE2K_RSAR0      0x08    // -w
 450030 #define NE2K_CRDA1      0x09    // r-
 450031 #define NE2K_RSAR1      0x09    // -w
 450032 #define NE2K_RBCR0      0x0A    // -w
 450033 #define NE2K_RBCR1      0x0B    // -w
 450034 #define NE2K_RSR        0x0C    // r-
 450035 #define NE2K_RCR        0x0C    // -w
 450036 #define NE2K_CNTR0      0x0D    // r-
 450037 #define NE2K_TCR        0x0D    // -w
 450038 #define NE2K_CNTR1      0x0E    // r-
 450039 #define NE2K_DCR        0x0E    // -w
 450040 #define NE2K_CNTR2      0x0F    // r-
 450041 #define NE2K_IMR        0x0F    // -w
 450042 //
 450043 // Page 1 registers: all read and write
 450044 //
 450045 #define NE2K_PAR0       0x01    // rw
 450046 #define NE2K_PAR1       0x02    // rw
 450047 #define NE2K_PAR2       0x03    // rw
 450048 #define NE2K_PAR3       0x04    // rw
 450049 #define NE2K_PAR4       0x05    // rw
 450050 #define NE2K_PAR5       0x06    // rw
 450051 #define NE2K_CURR       0x07    // rw
 450052 #define NE2K_MAR0       0x08    // rw
 450053 #define NE2K_MAR1       0x09    // rw
 450054 #define NE2K_MAR2       0x0A    // rw
 450055 #define NE2K_MAR3       0x0B    // rw
 450056 #define NE2K_MAR4       0x0C    // rw
 450057 #define NE2K_MAR5       0x0D    // rw
 450058 #define NE2K_MAR6       0x0E    // rw
 450059 #define NE2K_MAR7       0x0F    // rw
 450060 //
 450061 // Page 2 registers: read version of the same registers
 450062 // inside page 1:
 450063 //
 450064 //      NE2K_PSTART     0x01 // -w
 450065 //      NE2K_PSTOP      0x02 // -w
 450066 //      --              0x03
 450067 //      NE2K_TPSR       0x04 // -w
 450068 //      --              0x05
 450069 //      --              0x06
 450070 //      --              0x07
 450071 //      --              0x08
 450072 //      --              0x09
 450073 //      --              0x0A
 450074 //      --              0x0B
 450075 //      NE2K_RCR        0x0C // -w
 450076 //      NE2K_TCR        0x0D // -w
 450077 //      NE2K_DCR        0x0E // -w
 450078 //      NE2K_IMR        0x0F // -w
 450079 //
 450080 // Extra registers, outside pages.
 450081 //
 450082 #define NE2K_DATA       0x10    // Data port.
 450083 #define NE2K_RESET      0x1f    // Reset port.
 450084 //
 450085 // DMA buffer structure.
 450086 //
 450087 // 0x0000 .--------------------------.
 450088 //        |                          |
 450089 //        |                          |
 450090 //        |            ???           |
 450091 //        |                          |
 450092 //        |                          |
 450093 // 0x4000 |--------------------------|
 450094 //        | transmit buffer ring [1] |
 450095 // 0x4600 |--------------------------|
 450096 //        |                          |
 450097 //        |   receive buffer ring    |
 450098 //        |                          |
 450099 // 0xC000 |--------------------------|
 450100 //        |                          |
 450101 //        |           ???            |
 450102 //        |                          |
 450103 //        |                          |
 450104 //        `--------------------------' 0xFFFF
 450105 //
 450106 // [1] 0x600 is equal to 1536, that is the max space
 450107 //     that a packet can occupy inside the ring buffer.
 450108 //     So, there is the place for a
 450109 //     single transmission packet.
 450110 //
 450111 // Local DMA addresses:
 450112 //
 450113 #define NE2K_TX_START  0x40     // Means: 0x4000
 450114 #define NE2K_TX_STOP   0x46     // Means: 0x4600
 450115 
 450116 #define NE2K_RX_START  0x46     // Means: 0x4600
 450117 #define NE2K_RX_STOP   0xC0     // Means: 0xC000
 450118 //
 450119 // Transmit buffer (remote DMA).
 450120 //
 450121 #define NE2K_TX_BUFFER NE2K_TX_START
 450122 //
 450123 // SA-PROM (Station Address PROM) size
 450124 //
 450125 #define NE2K_SAPROM_SIZE 32     // 32 bytes
 450126 //----------------------------------------------------------
 450127 int ne2k_check (uintptr_t io);
 450128 int ne2k_isr (uintptr_t io);
 450129 int ne2k_isr_expect (uintptr_t io, unsigned int isr_expect);
 450130 int ne2k_reset (uintptr_t io, void *address);
 450131 int ne2k_rx (uintptr_t io);
 450132 int ne2k_rx_reset (uintptr_t io);
 450133 int ne2k_tx (uintptr_t io, void *buffer, size_t size);
 450134 //
 450135 void ne2k_test2 (int eth);
 450136 
 450137 
 450138 //----------------------------------------------------------
 450139 #endif

94.4.20   kernel/driver/nic/ne2k/ne2k_check.c

Si veda la sezione 93.16.

 460001 #include <kernel/driver/nic/ne2k.h>
 460002 #include <kernel/ibm_i386.h>
 460003 #include <errno.h>
 460004 //----------------------------------------------------------
 460005 int
 460006 ne2k_check (uintptr_t io)
 460007 {
 460008   int status;
 460009   int reg_00;
 460010   int reg_0d;
 460011   // 
 460012   // Read and save the command register (CR, 0x00): if 
 460013   // it is really the
 460014   // command register, should not be equal to 0xFF.
 460015   // 
 460016   reg_00 = in_8 (io + NE2K_CR);
 460017   if (reg_00 == 0xFF)
 460018     {
 460019       errset (E_DRIVER_FAULT);
 460020       return (-1);
 460021     }
 460022   // 
 460023   // Command register (CR)
 460024   // .-------------------------------.
 460025   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 460026   // |-------------------------------|
 460027   // | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0x61
 460028   // `-------------------------------'
 460029   // \___/ \_______/ |
 460030   // | | STOP
 460031   // | Abort/complete
 460032   // | remote DMA
 460033   // Register
 460034   // page 1
 460035   // 
 460036   // Stop and select page 1.
 460037   // 
 460038   out_8 ((io + NE2K_CR), 0x61);
 460039   // 
 460040   // Read, save and overwrite the register MAR5 (0x0D
 460041   // at
 460042   // page 1).
 460043   // 
 460044   reg_0d = in_8 (io + NE2K_MAR5);
 460045   out_8 (io + NE2K_MAR5, 0xFF);
 460046   // 
 460047   // Command register (CR)
 460048   // .-------------------------------.
 460049   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 460050   // |-------------------------------|
 460051   // | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0x21
 460052   // `-------------------------------'
 460053   // \___/ \_______/ |
 460054   // | | STOP
 460055   // | Abort/complete
 460056   // | remote DMA
 460057   // Register
 460058   // page 0
 460059   // 
 460060   // Stop and select page 0.
 460061   // 
 460062   out_8 ((io + NE2K_CR), 0x21);
 460063   // 
 460064   // Read the tally counter 0 (CNTR0) to clear it.
 460065   // 
 460066   in_8 (io + NE2K_CNTR0);
 460067   // 
 460068   // Now the tally counter 0 (CNTR0) should be zero.
 460069   // 
 460070   status = in_8 (io + NE2K_CNTR0);
 460071   if (status)
 460072     {
 460073       // 
 460074       // The value obtained is not zero, so it is not
 460075       // a NE2000 nic and the page change had probably
 460076       // no effect. So, restore the values found
 460077       // inside
 460078       // 0x00 and 0x0D, without trying to change page.
 460079       // 
 460080       out_8 (io, reg_00);
 460081       out_8 ((io + 0x0D), reg_0d);
 460082       errset (E_DRIVER_FAULT);
 460083       return (-1);
 460084     }
 460085   // 
 460086   // Everything is ok: it might be a NE2000 nic.
 460087   // 
 460088   return (0);
 460089 }

94.4.21   kernel/driver/nic/ne2k/ne2k_isr.c

Si veda la sezione 93.16.

 470001 #include <kernel/driver/pci.h>
 470002 #include <kernel/driver/nic/ne2k.h>
 470003 #include <kernel/ibm_i386.h>
 470004 #include <errno.h>
 470005 #include <kernel/lib_k.h>
 470006 #include <kernel/lib_s.h>
 470007 //----------------------------------------------------------
 470008 int
 470009 ne2k_isr (uintptr_t io)
 470010 {
 470011   int isr;
 470012   // 
 470013   // Get ISR (interrupt status register).
 470014   // 
 470015   isr = in_8 (io + NE2K_ISR);
 470016   // 
 470017   // 
 470018   // 
 470019   if (isr & 0x01)
 470020     {
 470021       // 
 470022       // Frame received.
 470023       // 
 470024       out_8 (io + NE2K_ISR, 0x01);
 470025       ne2k_rx (io);
 470026     }
 470027   if (isr & 0x04)
 470028     {
 470029       // 
 470030       // Frame received with errors.
 470031       // 
 470032       out_8 (io + NE2K_ISR, 0x04);
 470033     }
 470034   if (isr & 0x02)
 470035     {
 470036       // 
 470037       // Frame sent correctly.
 470038       // 
 470039       ;
 470040     }
 470041   if (isr & 0x08)
 470042     {
 470043       // 
 470044       // Frame sent with errors.
 470045       // 
 470046       ;
 470047     }
 470048   if (isr & 0x10)
 470049     {
 470050       k_printf ("OVERWRITE\n");
 470051       out_8 (io + NE2K_ISR, 0x10);
 470052       // 
 470053       // I don't understand if it works: Bochs just
 470054       // don't accept
 470055       // frames if they can make an overflow.
 470056       // 
 470057       ne2k_rx (io);
 470058       ne2k_rx_reset (io);
 470059     }
 470060   if (isr & 0x20)
 470061     {
 470062       // 
 470063       // Counter overflow.
 470064       // 
 470065       out_8 (io + NE2K_ISR, 0x20);
 470066     }
 470067   if (isr & 0x40)
 470068     {
 470069       // 
 470070       // Remote DMA complete.
 470071       // 
 470072       ;
 470073     }
 470074   if (isr & 0x80)
 470075     {
 470076       // 
 470077       // Reset status.
 470078       // 
 470079       ;
 470080     }
 470081   // 
 470082   // End.
 470083   // 
 470084   return (0);
 470085 }

94.4.22   kernel/driver/nic/ne2k/ne2k_isr_expect.c

Si veda la sezione 93.16.

 480001 #include <kernel/driver/nic/ne2k.h>
 480002 #include <kernel/ibm_i386.h>
 480003 #include <kernel/lib_k.h>
 480004 #include <errno.h>
 480005 #include <unistd.h>
 480006 #include <time.h>
 480007 //----------------------------------------------------------
 480008 #define DEBUG 0
 480009 //----------------------------------------------------------
 480010 int
 480011 ne2k_isr_expect (uintptr_t io, unsigned int isr_expect)
 480012 {
 480013   int retry = 5;
 480014   int status;
 480015   // 
 480016   // 
 480017   // 
 480018   for (; retry > 0; retry--)
 480019     {
 480020       status = in_8 (io + NE2K_ISR);
 480021       // 
 480022       if (status & isr_expect)
 480023         {
 480024           // 
 480025           // Reset the bit found true and exit loop.
 480026           // 
 480027           out_8 ((io + NE2K_ISR), isr_expect);
 480028           return (0);
 480029         }
 480030     }
 480031   // 
 480032   // If ISR is zero, we assume that it is ok.
 480033   // 
 480034   if (status == 0)
 480035     {
 480036       if (DEBUG)
 480037         {
 480038           k_printf ("[isr=0x%02x expect=0x%02x]",
 480039                     status, isr_expect);
 480040           return (0);
 480041         }
 480042       return (0);
 480043     }
 480044   else
 480045     {
 480046       if (DEBUG)
 480047         {
 480048           // 
 480049           // It is not zero, but we prefer to let it
 480050           // go...
 480051           // 
 480052           k_printf ("[isr=0x%02x expect=0x%02x]",
 480053                     status, isr_expect);
 480054           return (0);
 480055         }
 480056       else
 480057         {
 480058           errset (E_DRIVER_FAULT);
 480059           return (-1);
 480060         }
 480061     }
 480062 }

94.4.23   kernel/driver/nic/ne2k/ne2k_reset.c

Si veda la sezione 93.16.

 490001 #include <kernel/driver/pci.h>
 490002 #include <kernel/driver/nic/ne2k.h>
 490003 #include <kernel/ibm_i386.h>
 490004 #include <errno.h>
 490005 #include <kernel/lib_k.h>
 490006 #include <kernel/lib_s.h>
 490007 //----------------------------------------------------------
 490008 int
 490009 ne2k_reset (uintptr_t io, void *address)
 490010 {
 490011   int status;
 490012   int i;
 490013   uint8_t sa_prom[NE2K_SAPROM_SIZE];
 490014   uint8_t par[6];
 490015   // 
 490016   // ---------------------------------------------------
 490017   // RESET
 490018   // ---------------------------------------------------
 490019   // 
 490020   status = in_8 (io + NE2K_RESET);
 490021   out_8 ((io + NE2K_RESET), 0xFF);
 490022   out_8 ((io + NE2K_RESET), status);
 490023   // 
 490024   // Interrupt status register (ISR)
 490025   // .-------------------------------.
 490026   // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 490027   // |-------------------------------|
 490028   // | 1 | ? | ? | ? | ? | ? | ? | ? | 0x80
 490029   // `-------------------------------'
 490030   // |
 490031   // Reset status
 490032   // 
 490033   // Verify to have reset the NIC.
 490034   // 
 490035   status = ne2k_isr_expect (io, 0x80);
 490036   if (status)
 490037     {
 490038       errset (errno);
 490039       return (-1);
 490040     }
 490041   // 
 490042   // Reset all ISR register flags.
 490043   // 
 490044   out_8 ((io + NE2K_ISR), 0xFF);
 490045   // 
 490046   // ---------------------------------------------------
 490047   // GET ETHERNET ADDRESS FROM SA-PROM (Station
 490048   // Address PROM)
 490049   // ---------------------------------------------------
 490050   // 
 490051   // Command register (CR)
 490052   // .-------------------------------.
 490053   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 490054   // |-------------------------------|
 490055   // | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0x21
 490056   // `-------------------------------'
 490057   // \_____/ \_________/ |
 490058   // | | STOP
 490059   // | |
 490060   // | Abort/complete
 490061   // | remote DMA
 490062   // |
 490063   // Register
 490064   // page 0
 490065   // 
 490066   out_8 ((io + NE2K_CR), 0x21);
 490067   // 
 490068   // Interrupt status register (ISR)
 490069   // .-------------------------------.
 490070   // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 490071   // |-------------------------------|
 490072   // | 1 | ? | ? | ? | ? | ? | ? | ? | 0x80
 490073   // `-------------------------------'
 490074   // |
 490075   // Reset status
 490076   // 
 490077   // Verify to have reset the NIC.
 490078   // 
 490079   status = ne2k_isr_expect (io, 0x80);
 490080   if (status)
 490081     {
 490082       errset (errno);
 490083       return (-1);
 490084     }
 490085   // 
 490086   // Data configuration register (DCR)
 490087   // .-------------------------------.
 490088   // | - |FT1|FT0|ARM| LS|LAS|BOS|WTS|
 490089   // |-------------------------------|
 490090   // | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0x48
 490091   // `-------------------------------'
 490092   // \_____/ : | : : :
 490093   // | : | : : Byte DMA transfer
 490094   // | : | : :
 490095   // | : | : Little endian byte order
 490096   // | : | :
 490097   // | : | Dual 16 bit DMA mode
 490098   // | : |
 490099   // | : Loopback OFF (normal operation)
 490100   // | :
 490101   // | Send Command non executed: all frames removed
 490102   // from
 490103   // | Buffer Ring under program control
 490104   // |
 490105   // FIFO threshold 8 bytes
 490106   // 
 490107   out_8 ((io + NE2K_DCR), 0x48);
 490108   // 
 490109   // Reset remote byte count registers.
 490110   // 
 490111   out_8 ((io + NE2K_RBCR0), 0x00);
 490112   out_8 ((io + NE2K_RBCR1), 0x00);
 490113   // 
 490114   // Disable interrupts with an empty mask.
 490115   // 
 490116   out_8 ((io + NE2K_IMR), 0x00);
 490117   // 
 490118   // Reset all ISR register flags.
 490119   // 
 490120   out_8 ((io + NE2K_ISR), 0xFF);
 490121   // 
 490122   // Receive configuration register (RCR)
 490123   // .-------------------------------.
 490124   // | - | - |MON|PRO| AM| AB| AR|SEP|
 490125   // |-------------------------------|
 490126   // | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0x20
 490127   // `-------------------------------'
 490128   // | : : : : :
 490129   // | : : : : Frames with receive errors are
 490130   // | : : : : rejected
 490131   // | : : : :
 490132   // | : : : Frames with fewer than 64 bytes rejected
 490133   // | : : :
 490134   // | : : Frames with broadcast destination rejected
 490135   // | : : accepted
 490136   // | : :
 490137   // | : Frames with multicast destination address
 490138   // | : not checked
 490139   // | :
 490140   // | Physical address of node must match the station
 490141   // | address
 490142   // |
 490143   // Monitor mode: frames checked but not buffered to
 490144   // memory
 490145   // 
 490146   // Monitor mode.
 490147   // 
 490148   out_8 ((io + NE2K_RCR), 0x20);
 490149   // 
 490150   // Transmit configuration register (TCR)
 490151   // .--------------------------------.
 490152   // | - | - | - |OFST|ATD|LB1|LB0|CRC|
 490153   // |--------------------------------|
 490154   // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0x02
 490155   // `--------------------------------'
 490156   // \_____/ :
 490157   // | CRC appended by the transmitter
 490158   // |
 490159   // Internal loopback (mode 1)
 490160   // 
 490161   // [Loopback is not supported by Bochs]
 490162   // 
 490163   // Transmit loopback.
 490164   // 
 490165   out_8 ((io + NE2K_TCR), 0x02);
 490166   // 
 490167   // Remote byte count registers to NE2K_SAPROM_SIZE:
 490168   // the bytes to be
 490169   // read from SA-PROM.
 490170   // 
 490171   out_8 ((io + NE2K_RBCR0), NE2K_SAPROM_SIZE);
 490172   out_8 ((io + NE2K_RBCR1), (NE2K_SAPROM_SIZE >> 8));
 490173   // 
 490174   // Set the remote DMA address to zero.
 490175   // 
 490176   out_8 ((io + NE2K_RSAR0), 0x00);      // Must be
 490177   // zero.
 490178   out_8 ((io + NE2K_RSAR1), 0x00);
 490179   // 
 490180   // Command register (CR)
 490181   // .-------------------------------.
 490182   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 490183   // |-------------------------------|
 490184   // | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0x0A
 490185   // `-------------------------------'
 490186   // \___/ \_______/ |
 490187   // | | START
 490188   // | Read
 490189   // |
 490190   // Register
 490191   // page 0
 490192   // 
 490193   out_8 ((io + NE2K_CR), 0x0A);
 490194   // 
 490195   // Save the SA-PROM content.
 490196   // 
 490197   for (i = 0; i < NE2K_SAPROM_SIZE; i++)
 490198     {
 490199       sa_prom[i] = in_8 (io + NE2K_DATA);
 490200     }
 490201   // 
 490202   // Set NIC physical address from SA-PROM data.
 490203   // 
 490204   par[0] = sa_prom[0];
 490205   par[1] = sa_prom[2];
 490206   par[2] = sa_prom[4];
 490207   par[3] = sa_prom[6];
 490208   par[4] = sa_prom[8];
 490209   par[5] = sa_prom[10];
 490210   // 
 490211   // Copy to the `address' pointer.
 490212   // 
 490213   if (address != NULL)
 490214     {
 490215       memcpy (address, par, (size_t) 6);
 490216     }
 490217   // 
 490218   // ---------------------------------------------------
 490219   // INITIALIZATION SEQUENCE
 490220   // ---------------------------------------------------
 490221   // 
 490222   // Command register (CR)
 490223   // .-------------------------------.
 490224   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 490225   // |-------------------------------|
 490226   // | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0x21
 490227   // `-------------------------------'
 490228   // \_____/ \_________/ |
 490229   // | | STOP
 490230   // | |
 490231   // | Abort/complete
 490232   // | remote DMA
 490233   // |
 490234   // Register
 490235   // page 0
 490236   // 
 490237   out_8 ((io + NE2K_CR), 0x21);
 490238   // 
 490239   // There is no need to check the ISR value. At this
 490240   // point,
 490241   // ISR might report a reset status or a remote DMA
 490242   // complete.
 490243   // Go to the DCR register.
 490244   // 
 490245   // Data configuration register (DCR)
 490246   // .-------------------------------.
 490247   // | - |FT1|FT0|ARM| LS|LAS|BOS|WTS|
 490248   // |-------------------------------|
 490249   // | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0x48
 490250   // `-------------------------------'
 490251   // \_____/ : | : : :
 490252   // | : | : : Byte DMA transfer
 490253   // | : | : :
 490254   // | : | : Little endian byte order
 490255   // | : | :
 490256   // | : | Dual 16 bit DMA mode
 490257   // | : |
 490258   // | : Loopback OFF (normal operation)
 490259   // | :
 490260   // | Send Command non executed: all frames removed
 490261   // from
 490262   // | Buffer Ring under program control
 490263   // |
 490264   // FIFO threshold 8 bytes
 490265   // 
 490266   out_8 ((io + NE2K_DCR), 0x48);
 490267   // 
 490268   // Reset remote byte count registers.
 490269   // 
 490270   out_8 ((io + NE2K_RBCR0), 0x00);
 490271   out_8 ((io + NE2K_RBCR1), 0x00);
 490272   // 
 490273   // Receive configuration register (RCR)
 490274   // .-------------------------------.
 490275   // | - | - |MON|PRO| AM| AB| AR|SEP|
 490276   // |-------------------------------|
 490277   // | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0x04
 490278   // `-------------------------------'
 490279   // : : : | : :
 490280   // : : : | : Frames with receive errors are
 490281   // : : : | : rejected
 490282   // : : : | :
 490283   // : : : | Frames with fewer than 64 bytes rejected
 490284   // : : : |
 490285   // : : : Frames with broadcast destination address
 490286   // : : : accepted
 490287   // : : :
 490288   // : : Frames with multicast destination address
 490289   // : : not checked
 490290   // : :
 490291   // : Physical address of node must match the station
 490292   // : address
 490293   // :
 490294   // Frames buffered to memory
 490295   // 
 490296   // Normal operation and broadcast accepted.
 490297   // 
 490298   out_8 ((io + NE2K_RCR), 0x04);
 490299   // 
 490300   // Transmit page start (local DMA).
 490301   // 
 490302   out_8 ((io + NE2K_TPSR), NE2K_TX_START);
 490303   // 
 490304   // Transmit configuration register (TCR)
 490305   // .--------------------------------.
 490306   // | - | - | - |OFST|ATD|LB1|LB0|CRC|
 490307   // |--------------------------------|
 490308   // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0x02
 490309   // `--------------------------------'
 490310   // \_____/ :
 490311   // | CRC appended by the transmitter
 490312   // |
 490313   // Internal loopback (mode 1)
 490314   // 
 490315   // [Loopback is not supported by Bochs]
 490316   // 
 490317   // Transmit loopback.
 490318   // 
 490319   out_8 ((io + NE2K_TCR), 0x02);
 490320   // 
 490321   // Set receive buffer page start (local DMA).
 490322   // 
 490323   out_8 ((io + NE2K_PSTART), NE2K_RX_START);
 490324   // 
 490325   // Set boundary: the frame not yet read. At the
 490326   // moment, it is the same
 490327   // as the receive buffer page start.
 490328   // 
 490329   out_8 ((io + NE2K_BNRY), NE2K_RX_START);
 490330   // 
 490331   // Set receive buffer page stop (local DMA).
 490332   // 
 490333   out_8 ((io + NE2K_PSTOP), NE2K_RX_STOP);
 490334   // 
 490335   // Command register (CR)
 490336   // .-------------------------------.
 490337   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 490338   // |-------------------------------|
 490339   // | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0x61
 490340   // `-------------------------------'
 490341   // \_____/ \_________/ |
 490342   // | | STOP
 490343   // | |
 490344   // | Abort/complete
 490345   // | remote DMA
 490346   // |
 490347   // Register
 490348   // page 1
 490349   // 
 490350   out_8 ((io + NE2K_CR), 0x61);
 490351   // 
 490352   // Save physical address and multicast address.
 490353   // 
 490354   out_8 ((io + NE2K_PAR0), par[0]);
 490355   out_8 ((io + NE2K_PAR1), par[1]);
 490356   out_8 ((io + NE2K_PAR2), par[2]);
 490357   out_8 ((io + NE2K_PAR3), par[3]);
 490358   out_8 ((io + NE2K_PAR4), par[4]);
 490359   out_8 ((io + NE2K_PAR5), par[5]);
 490360   // 
 490361   out_8 ((io + NE2K_MAR0), 0);
 490362   out_8 ((io + NE2K_MAR1), 0);
 490363   out_8 ((io + NE2K_MAR2), 0);
 490364   out_8 ((io + NE2K_MAR3), 0);
 490365   out_8 ((io + NE2K_MAR4), 0);
 490366   out_8 ((io + NE2K_MAR5), 0);
 490367   out_8 ((io + NE2K_MAR6), 0);
 490368   out_8 ((io + NE2K_MAR7), 0);
 490369   // 
 490370   // Set current page: the first frame to be saved
 490371   // inside the receive
 490372   // buffer. At the moment, it is the same as the
 490373   // buffer page start.
 490374   // 
 490375   out_8 ((io + NE2K_CURR), NE2K_RX_START);
 490376   // 
 490377   // Command register (CR)
 490378   // .-------------------------------.
 490379   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 490380   // |-------------------------------|
 490381   // | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0x22
 490382   // `-------------------------------'
 490383   // \_____/ \_________/ |
 490384   // | | START
 490385   // | |
 490386   // | Abort/complete
 490387   // | remote DMA
 490388   // |
 490389   // Register
 490390   // page 0
 490391   // 
 490392   out_8 ((io + NE2K_CR), 0x22);
 490393   // 
 490394   // Reset all ISR register flags.
 490395   // 
 490396   out_8 ((io + NE2K_ISR), 0xFF);
 490397   // 
 490398   // ISR will be polled, but received packets will
 490399   // fire the IRQ,
 490400   // although it is not necessary. So the IMR
 490401   // (Interrupt mask register)
 490402   // is now set properly with the value 0x01.
 490403   // 
 490404   // Interrupt mask register (IMR)
 490405   // .---------------------------------------.
 490406   // | -- |RDCE|CNTE|OVWE|TXEE|RXEE|PTXE|PRXE|
 490407   // |---------------------------------------|
 490408   // | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0x01
 490409   // `---------------------------------------'
 490410   // |
 490411   // Enable interrupt when packet
 490412   // received
 490413   // 
 490414   out_8 ((io + NE2K_IMR), 0x01);
 490415   // 
 490416   // Transmit configuration register (TCR)
 490417   // .--------------------------------.
 490418   // | - | - | - |OFST|ATD|LB1|LB0|CRC|
 490419   // |--------------------------------|
 490420   // | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0x00
 490421   // `--------------------------------'
 490422   // 
 490423   // Normal operation.
 490424   // 
 490425   out_8 ((io + NE2K_TCR), 0x00);
 490426   // 
 490427   return (0);
 490428 }

94.4.24   kernel/driver/nic/ne2k/ne2k_rx.c

Si veda la sezione 93.16.

 500001 #include <kernel/driver/pci.h>
 500002 #include <kernel/net.h>
 500003 #include <kernel/driver/nic/ne2k.h>
 500004 #include <kernel/ibm_i386.h>
 500005 #include <errno.h>
 500006 #include <kernel/lib_k.h>
 500007 #include <kernel/lib_s.h>
 500008 //----------------------------------------------------------
 500009 #define DEBUG 0
 500010 //----------------------------------------------------------
 500011 int
 500012 ne2k_rx (uintptr_t io)
 500013 {
 500014   int i;
 500015   int bytes;
 500016   int curr;
 500017   int bnry;
 500018   int next;
 500019   int frame_status;
 500020   int frame_size;
 500021   int status;
 500022   int n = net_index_eth (0, NULL, io);
 500023   net_buffer_eth_t *buffer;
 500024   // 
 500025   // Verify to have found a valid Ethernet device.
 500026   // 
 500027   if (n < 0)
 500028     {
 500029       errset (ENODEV);
 500030       return (-1);
 500031     }
 500032   // 
 500033   // Command register (CR)
 500034   // .-------------------------------.
 500035   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 500036   // |-------------------------------|
 500037   // | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0x62
 500038   // `-------------------------------'
 500039   // \_____/ \_________/ |
 500040   // | | START
 500041   // | |
 500042   // | Abort/complete remote DMA
 500043   // |
 500044   // Register page 1
 500045   // 
 500046   out_8 ((io + NE2K_CR), 0x62);
 500047   // 
 500048   // Get the current position.
 500049   // 
 500050   curr = in_8 (io + NE2K_CURR);
 500051   // 
 500052   // Command register (CR)
 500053   // .-------------------------------.
 500054   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 500055   // |-------------------------------|
 500056   // | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0x22
 500057   // `-------------------------------'
 500058   // \_____/ \_________/ |
 500059   // | | START
 500060   // | |
 500061   // | Abort/complete remote DMA
 500062   // |
 500063   // Register page 0
 500064   // 
 500065   out_8 ((io + NE2K_CR), 0x22);
 500066   // 
 500067   // Get the boundary.
 500068   // 
 500069   bnry = in_8 (io + NE2K_BNRY);
 500070   // 
 500071   // ---------------------------------------------------
 500072   // The function is run because at least a frame was
 500073   // received:
 500074   // if index `bnry' and index `curr' are the same,
 500075   // all the receive
 500076   // ring buffer is to be copied.
 500077   // ---------------------------------------------------
 500078   // 
 500079   // Get all the frames ready from the internal
 500080   // buffer.
 500081   // 
 500082   while (1)
 500083     {
 500084       // 
 500085       // Find a place inside the frame table.
 500086       // 
 500087       buffer = net_buffer_eth (n);
 500088       // 
 500089       // Check to have a valid buffer pointer.
 500090       // 
 500091       if (buffer == NULL)
 500092         {
 500093           errset (errno);
 500094           return (-1);
 500095         }
 500096       // 
 500097       // First read 4 bytes starting from `bnry'.
 500098       // 
 500099       out_8 ((io + NE2K_RBCR0), 4);
 500100       out_8 ((io + NE2K_RBCR1), 0);
 500101       // 
 500102       // Set the remote DMA address to bnry.
 500103       // 
 500104       out_8 ((io + NE2K_RSAR0), 0x00);  // Must be
 500105       // zero.
 500106       out_8 ((io + NE2K_RSAR1), bnry);
 500107       // 
 500108       // Command register (CR)
 500109       // .-------------------------------.
 500110       // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 500111       // |-------------------------------|
 500112       // | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0x0A
 500113       // `-------------------------------'
 500114       // \_____/ \_________/ |
 500115       // | | START
 500116       // | |
 500117       // | Read
 500118       // |
 500119       // Register page 0
 500120       // 
 500121       out_8 (io + NE2K_CR, 0x0A);
 500122       // 
 500123       // Frame status
 500124       // 
 500125       frame_status = in_8 (io + NE2K_DATA);
 500126       // 
 500127       // Next frame.
 500128       // 
 500129       next = in_8 (io + NE2K_DATA);
 500130       // 
 500131       // Frame size low.
 500132       // 
 500133       frame_size = in_8 (io + NE2K_DATA);
 500134       // 
 500135       // Frame size high
 500136       // 
 500137       frame_size += (in_8 (io + NE2K_DATA) * 256);
 500138       // 
 500139       // Interrupt status register (ISR)
 500140       // .-------------------------------.
 500141       // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 500142       // |-------------------------------|
 500143       // | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0x40
 500144       // `-------------------------------'
 500145       // |
 500146       // Remote DMA complete
 500147       // 
 500148       // Verify to have finished with DMA transfer.
 500149       // 
 500150       status = ne2k_isr_expect (io, 0x40);
 500151       if (status)
 500152         {
 500153           errset (errno);
 500154           return (-1);
 500155         }
 500156       // 
 500157       // Now read again all the frame plus header (the 
 500158       // initial 4 bytes).
 500159       // 
 500160       buffer->clock = k_clock ();
 500161       buffer->size = frame_size - 4;
 500162       // 
 500163       if (DEBUG)
 500164         {
 500165           k_printf
 500166             ("0x%02x[BNRY=0x%02x "
 500167              "CURR=0x%02x]0x%02x size=%i\n",
 500168              NE2K_RX_START, bnry, curr, NE2K_RX_STOP,
 500169              frame_size);
 500170         }
 500171       // 
 500172       if (next == bnry)
 500173         {
 500174           k_printf
 500175             ("[%s] next==bnry but should "
 500176              "not happen!\n", __func__);
 500177           errset (E_DRIVER_FAULT);
 500178           return (-1);
 500179         }
 500180       // 
 500181       if (next > bnry)
 500182         {
 500183           bytes = frame_size;
 500184         }
 500185       // 
 500186       if (next < bnry)
 500187         {
 500188           // 
 500189           // Read up to the bottom.
 500190           // 
 500191           bytes = ((NE2K_RX_STOP - bnry) * 256);
 500192           bytes = min (bytes, frame_size);
 500193         }
 500194       // 
 500195       // Read frame content: first part.
 500196       // 
 500197       out_8 ((io + NE2K_RBCR0), bytes & 0xFF);
 500198       out_8 ((io + NE2K_RBCR1), bytes >> 8);
 500199       // 
 500200       out_8 ((io + NE2K_RSAR0), 0);     // MUST be
 500201       // zero. :-(
 500202       out_8 ((io + NE2K_RSAR1), bnry);
 500203       // 
 500204       // Command register (CR)
 500205       // .-------------------------------.
 500206       // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 500207       // |-------------------------------|
 500208       // | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0x0A
 500209       // `-------------------------------'
 500210       // \_____/ \_________/ |
 500211       // | | START
 500212       // | |
 500213       // | Read
 500214       // |
 500215       // Register page 0
 500216       // 
 500217       out_8 (io + NE2K_CR, 0x0A);
 500218       // 
 500219       // Jump the first four bytes (no way to start
 500220       // after
 500221       // the page start).
 500222       // 
 500223       in_8 (io + NE2K_DATA);
 500224       in_8 (io + NE2K_DATA);
 500225       in_8 (io + NE2K_DATA);
 500226       in_8 (io + NE2K_DATA);
 500227       bytes -= 4;
 500228       // 
 500229       // Get the frame data.
 500230       // 
 500231       i = 0;
 500232       for (; bytes > 0; i++, bytes--)
 500233         {
 500234           buffer->frame.octet[i] = in_8 (io + NE2K_DATA);
 500235         }
 500236       // 
 500237       // Interrupt status register (ISR)
 500238       // .-------------------------------.
 500239       // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 500240       // |-------------------------------|
 500241       // | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0x40
 500242       // `-------------------------------'
 500243       // |
 500244       // Remote DMA complete
 500245       // 
 500246       // Verify to have finished with DMA transfer.
 500247       // 
 500248       status = ne2k_isr_expect (io, 0x40);
 500249       if (status)
 500250         {
 500251           errset (errno);
 500252           return (-1);
 500253         }
 500254       // 
 500255       if (next < bnry)
 500256         {
 500257           // 
 500258           // There might be a second part to read.
 500259           // 
 500260           bytes =
 500261             frame_size - ((NE2K_RX_STOP - bnry) * 256);
 500262         }
 500263       // 
 500264       if (bytes > 0)
 500265         {
 500266           // 
 500267           out_8 ((io + NE2K_RBCR0), bytes & 0xFF);
 500268           out_8 ((io + NE2K_RBCR1), bytes >> 8);
 500269           // 
 500270           out_8 ((io + NE2K_RSAR0), 0);
 500271           out_8 ((io + NE2K_RSAR1), NE2K_RX_START);
 500272           // 
 500273           // Command register (CR)
 500274           // .-------------------------------.
 500275           // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 500276           // |-------------------------------|
 500277           // | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0x0A
 500278           // `-------------------------------'
 500279           // \_____/ \_________/ |
 500280           // | | START
 500281           // | |
 500282           // | Read
 500283           // |
 500284           // Register page 0
 500285           // 
 500286           out_8 (io + NE2K_CR, 0x0A);
 500287           // 
 500288           for (; bytes > 0; i++, bytes--)
 500289             {
 500290               buffer->frame.octet[i] =
 500291                 in_8 (io + NE2K_DATA);
 500292             }
 500293           // 
 500294           // Interrupt status register (ISR)
 500295           // .-------------------------------.
 500296           // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 500297           // |-------------------------------|
 500298           // | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0x40
 500299           // `-------------------------------'
 500300           // |
 500301           // Remote DMA complete
 500302           // 
 500303           // Verify to have finished with DMA
 500304           // transfer.
 500305           // 
 500306           status = ne2k_isr_expect (io, 0x40);
 500307           if (status)
 500308             {
 500309               errset (errno);
 500310               return (-1);
 500311             }
 500312         }
 500313       // 
 500314       // Update BNRY.
 500315       // 
 500316       bnry = next;
 500317       out_8 (io + NE2K_BNRY, bnry);
 500318       // 
 500319       // If the new bnry is equal to curr, the loop is 
 500320       // finished.
 500321       // 
 500322       if (bnry == curr)
 500323         {
 500324           // 
 500325           // finish.
 500326           // 
 500327           return (0);
 500328         }
 500329     }
 500330 }

94.4.25   kernel/driver/nic/ne2k/ne2k_rx_reset.c

Si veda la sezione 93.16.

 510001 #include <kernel/driver/pci.h>
 510002 #include <kernel/driver/nic/ne2k.h>
 510003 #include <kernel/ibm_i386.h>
 510004 #include <errno.h>
 510005 #include <kernel/lib_k.h>
 510006 #include <kernel/lib_s.h>
 510007 //----------------------------------------------------------
 510008 #define DEBUG 1
 510009 //----------------------------------------------------------
 510010 int
 510011 ne2k_rx_reset (uintptr_t io)
 510012 {
 510013   int status;
 510014   // 
 510015   // Command register (CR)
 510016   // .-------------------------------.
 510017   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 510018   // |-------------------------------|
 510019   // | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0x21
 510020   // `-------------------------------'
 510021   // \_____/ \_________/ |
 510022   // | | STOP
 510023   // | |
 510024   // | Abort/complete remote DMA
 510025   // |
 510026   // Register page 0
 510027   // 
 510028   out_8 ((io + NE2K_CR), 0x21);
 510029   // 
 510030   // Interrupt status register (ISR)
 510031   // .-------------------------------.
 510032   // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 510033   // |-------------------------------|
 510034   // | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0x80
 510035   // `-------------------------------'
 510036   // |
 510037   // Reset
 510038   // 
 510039   status = ne2k_isr_expect (io, 0x80);
 510040   if (status)
 510041     {
 510042       errset (errno);
 510043       return (-1);
 510044     }
 510045   // 
 510046   // 
 510047   // 
 510048   out_8 ((io + NE2K_RBCR0), 0);
 510049   out_8 ((io + NE2K_RBCR1), 0);
 510050   // 
 510051   // Command register (CR)
 510052   // .-------------------------------.
 510053   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 510054   // |-------------------------------|
 510055   // | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0x22
 510056   // `-------------------------------'
 510057   // \_____/ \_________/ |
 510058   // | | START
 510059   // | |
 510060   // | Abort/complete remote DMA
 510061   // |
 510062   // Register page 0
 510063   // 
 510064   out_8 (io + NE2K_CR, 0x22);
 510065   // 
 510066   return (0);
 510067 }

94.4.26   kernel/driver/nic/ne2k/ne2k_tx.c

Si veda la sezione 93.16.

 520001 #include <kernel/driver/pci.h>
 520002 #include <kernel/driver/nic/ne2k.h>
 520003 #include <kernel/ibm_i386.h>
 520004 #include <errno.h>
 520005 #include <kernel/lib_k.h>
 520006 #include <kernel/lib_s.h>
 520007 //----------------------------------------------------------
 520008 int
 520009 ne2k_tx (uintptr_t io, void *buffer, size_t size)
 520010 {
 520011   int i;
 520012   int status;
 520013   uint8_t *b = buffer;
 520014   // 
 520015   // Read the command register to see if the NIC is
 520016   // transmitting.
 520017   // The value 0x26 tells that the NIC is
 520018   // transmitting.
 520019   // 
 520020   // Command register (CR)
 520021   // .-------------------------------.
 520022   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 520023   // |-------------------------------|
 520024   // | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0x26
 520025   // `-------------------------------'
 520026   // \_____/ \_________/ | |
 520027   // | | | Start
 520028   // | | Transmit frame
 520029   // | Abort/complete
 520030   // | remote DMA
 520031   // Register
 520032   // page 0
 520033   // 
 520034   status = in_8 (io + NE2K_CR);
 520035   if (status == 0x26)
 520036     {
 520037       errset (EBUSY);
 520038       return (-1);
 520039     }
 520040   // 
 520041   // Set up the frame size: the size is split into
 520042   // RBCR0 and RBCR1
 520043   // registers.
 520044   // 
 520045   out_8 ((io + NE2K_RBCR0), (size & 0xFF));
 520046   out_8 ((io + NE2K_RBCR1), (size >> 8));
 520047   // 
 520048   // Set the remote DMA address.
 520049   // 
 520050   out_8 ((io + NE2K_RSAR0), 0x00);      // Must be
 520051   // zero.
 520052   out_8 ((io + NE2K_RSAR1), NE2K_TX_BUFFER);
 520053   // 
 520054   // Command register (CR)
 520055   // .-------------------------------.
 520056   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 520057   // |-------------------------------|
 520058   // | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0x12
 520059   // `-------------------------------'
 520060   // \_____/ \_________/ |
 520061   // | | Start
 520062   // | |
 520063   // | Write
 520064   // Register
 520065   // page 0
 520066   // 
 520067   out_8 ((io + NE2K_CR), 0x12);
 520068   // 
 520069   // Write to the data port all the frame.
 520070   // 
 520071   for (i = 0; i < size; i++)
 520072     {
 520073       out_8 ((io + NE2K_DATA), b[i]);
 520074     }
 520075   // 
 520076   // Interrupt status register (ISR)
 520077   // .-------------------------------.
 520078   // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 520079   // |-------------------------------|
 520080   // | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0x40
 520081   // `-------------------------------'
 520082   // |
 520083   // Remote DMA complete
 520084   // 
 520085   // Verify to have finished with DMA transfer.
 520086   // 
 520087   status = ne2k_isr_expect (io, 0x40);
 520088   if (status)
 520089     {
 520090       errset (errno);
 520091       return (-1);
 520092     }
 520093   // 
 520094   // Set transmit page start, to the transmit buffer.
 520095   // 
 520096   out_8 (io + NE2K_TPSR, NE2K_TX_BUFFER);
 520097   // 
 520098   // Set transmit byte count (frame size).
 520099   // 
 520100   out_8 ((io + NE2K_TBCR0), (size & 0xFF));
 520101   out_8 ((io + NE2K_TBCR1), (size >> 8));
 520102   // 
 520103   // Command register (CR)
 520104   // .-------------------------------.
 520105   // |PS1|PS0|RD2|RD1|RD0|TXP|STA|STP|
 520106   // |-------------------------------|
 520107   // | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0x26
 520108   // `-------------------------------'
 520109   // \_____/ \_________/ | |
 520110   // | | | Start
 520111   // | | Transmit frame
 520112   // | Abort/complete remote DMA
 520113   // Register
 520114   // page 0
 520115   // 
 520116   // Send frame!
 520117   // 
 520118   out_8 ((io + NE2K_CR), 0x26);
 520119   // 
 520120   // Interrupt status register (ISR)
 520121   // .-------------------------------.
 520122   // |RST|RDC|CNT|OVW|TXE|RXE|PTX|PRX|
 520123   // |-------------------------------|
 520124   // | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0x0A
 520125   // `-------------------------------'
 520126   // | |
 520127   // | Frame transmitted with no errors
 520128   // Transmit error
 520129   // 
 520130   // Wait the end of transmission: might get a good
 520131   // transmission
 520132   // report, or an error transmission report.
 520133   // 
 520134   status = ne2k_isr_expect (io, 0x0A);
 520135   if (status)
 520136     {
 520137       errset (errno);
 520138       return (-1);
 520139     }
 520140   // 
 520141   // Transmit status (TSR)
 520142   // .-------------------------------.
 520143   // |OWC|CDH| FU|CRS|ABT|COL| - |PTX|
 520144   // |-------------------------------|
 520145   // | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0x38
 520146   // `-------------------------------'
 520147   // | | |
 520148   // | | Transmit aborted
 520149   // | Carrier sense lost
 520150   // FIFO underrun
 520151   // 
 520152   // Check if there was an error, during transmission.
 520153   // 
 520154   status = in_8 (io + NE2K_TSR);
 520155   if (status & 0x38)
 520156     {
 520157       errset (EIO);
 520158       return (-1);
 520159     }
 520160   // 
 520161   // Done.
 520162   // 
 520163   return (0);
 520164 //
 520165 }

94.4.27   kernel/driver/pci.h

Si veda la sezione 93.19.

 530001 #ifndef _KERNEL_DRIVER_PCI_H
 530002 #define _KERNEL_DRIVER_PCI_H    1
 530003 //----------------------------------------------------------
 530004 #include <stdint.h>
 530005 #include <sys/types.h>
 530006 //----------------------------------------------------------
 530007 //
 530008 #define PCI_MAX_DEVICES                 8
 530009 #define PCI_MAX_BUSES                 256       // Fixed.
 530010 #define PCI_MAX_SLOTS                  32       // Fixed.
 530011 //
 530012 #define PCI_CONFIG_ADDRESS         0x0CF8
 530013 #define PCI_CONFIG_DATA            0x0CFC
 530014 //
 530015 // CONFIG_ADDRESS register structure.
 530016 //
 530017 typedef union
 530018 {
 530019   uint32_t selector;
 530020   struct
 530021   {
 530022     uint32_t zero:2,
 530023       reg:6,
 530024       function:3, slot:5, bus:8, reserved:7, enable:1;
 530025   };
 530026 } pci_address_t;
 530027 //
 530028 // CONFIG_DATA register structures.
 530029 //
 530030 typedef union
 530031 {
 530032   uint32_t r[16];
 530033   struct
 530034   {
 530035     struct
 530036     {
 530037       uint32_t vendor_id:16, device_id:16;
 530038       // 
 530039       uint32_t command:16, status:16;
 530040       // 
 530041       uint32_t revision_id:8,
 530042         prog_if:8, subclass:8, class_code:8;
 530043       // 
 530044       uint32_t cache_line_size:8,
 530045         latency_timer:8,
 530046         header_type:7, multi_function:1, bist:8;
 530047       // 
 530048       uint32_t bar0;
 530049       uint32_t bar1;
 530050       uint32_t bar2;
 530051       uint32_t bar3;
 530052       uint32_t bar4;
 530053       uint32_t bar5;
 530054       uint32_t cardbus_cis_pointer;
 530055       uint32_t expansion_rom_base_address;
 530056       // 
 530057       uint32_t subsystem_vendor_id:16, subsystem_id:16;
 530058       // 
 530059       uint32_t capabilities_pointer:8, reserved_1:24;
 530060       // 
 530061       uint32_t reserved_2;
 530062       // 
 530063       uint32_t interrupt_line:8,
 530064         interrupt_pin:8, min_grant:8, max_latency:8;
 530065     };
 530066   };
 530067 } pci_header_type_00_t;
 530068 //
 530069 //----------------------------------------------------------
 530070 //
 530071 // PCI table row.
 530072 //
 530073 typedef struct
 530074 {
 530075   unsigned char bus;
 530076   unsigned char slot;
 530077   unsigned short int vendor_id;
 530078   unsigned short int device_id;
 530079   unsigned char class_code;
 530080   unsigned char subclass;
 530081   unsigned char prog_if;
 530082   uintptr_t base_io;
 530083   unsigned char irq;
 530084 } pci_t;
 530085 //
 530086 extern pci_t pci_table[PCI_MAX_DEVICES];
 530087 //
 530088 //----------------------------------------------------------
 530089 void pci_init (void);
 530090 //----------------------------------------------------------
 530091 #endif

94.4.28   kernel/driver/pci/pci_init.c

Si veda la sezione 93.19.

 540001 #include <kernel/driver/pci.h>
 540002 #include <kernel/ibm_i386.h>
 540003 #include <errno.h>
 540004 //----------------------------------------------------------
 540005 extern pci_t pci_table[PCI_MAX_DEVICES];
 540006 //----------------------------------------------------------
 540007 void
 540008 pci_init (void)
 540009 {
 540010   pci_header_type_00_t pci;
 540011   pci_address_t pci_addr;
 540012   // 
 540013   int t;        // PCI table index.
 540014   int b;        // PCI bus index.
 540015   int s;        // PCI slot index.
 540016   int r;        // PCI header register index.
 540017   // 
 540018   // Reset the PCI table.
 540019   // 
 540020   for (t = 0; t < PCI_MAX_DEVICES; t++)
 540021     {
 540022       pci_table[t].bus = 0;
 540023       pci_table[t].slot = 0;
 540024       pci_table[t].vendor_id = 0;
 540025       pci_table[t].device_id = 0;
 540026       pci_table[t].class_code = 0;
 540027       pci_table[t].subclass = 0;
 540028       pci_table[t].prog_if = 0;
 540029       pci_table[t].base_io = 0;
 540030       pci_table[t].irq = 0;
 540031     }
 540032   // 
 540033   // Scan PCI buses and slots.
 540034   // 
 540035   t = 0;
 540036   // 
 540037   for (b = 0; b < PCI_MAX_BUSES && t < PCI_MAX_DEVICES; b++)
 540038     {
 540039       // 
 540040       // Will not check multi functions devices (we
 540041       // are shure that
 540042       // we don't have them).
 540043       // 
 540044       for (s = 0;
 540045            s < PCI_MAX_SLOTS && t < PCI_MAX_DEVICES; s++)
 540046         {
 540047           pci_addr.selector = 0;
 540048           pci_addr.enable = 1;
 540049           pci_addr.bus = b;
 540050           pci_addr.slot = s;
 540051           // 
 540052           pci_addr.reg = 0;
 540053           out_32 (PCI_CONFIG_ADDRESS, pci_addr.selector);
 540054           pci.r[0] = in_32 (PCI_CONFIG_DATA);
 540055           // 
 540056           if (pci.r[0] == 0xFFFFFFFF)
 540057             {
 540058               // 
 540059               // There is no such bus:slot
 540060               // combination!
 540061               // 
 540062               continue;
 540063             }
 540064           else
 540065             {
 540066               for (r = 1; r < 16; r++)
 540067                 {
 540068                   pci_addr.reg = r;
 540069                   out_32 (PCI_CONFIG_ADDRESS,
 540070                           pci_addr.selector);
 540071                   pci.r[r] = in_32 (PCI_CONFIG_DATA);
 540072                 }
 540073             }
 540074           // 
 540075           // We consider only PCI header type 0x00!
 540076           // 
 540077           if (pci.header_type != 0)
 540078             {
 540079               continue;
 540080             }
 540081           // 
 540082           // We do not consider PCI bridge devices!
 540083           // 
 540084           if (pci.class_code == 0x06)
 540085             {
 540086               continue;
 540087             }
 540088           // 
 540089           // Save the device inside the PCI table.
 540090           // 
 540091           pci_table[t].bus = b;
 540092           pci_table[t].slot = s;
 540093           pci_table[t].vendor_id = pci.vendor_id;
 540094           pci_table[t].device_id = pci.device_id;
 540095           pci_table[t].class_code = pci.class_code;
 540096           pci_table[t].subclass = pci.subclass;
 540097           pci_table[t].prog_if = pci.prog_if;
 540098           pci_table[t].base_io = pci.bar0 & 0xFFFFFFFC;
 540099           pci_table[t].irq = pci.interrupt_line;
 540100           // 
 540101           k_printf ("[%s]: %04x:%04x io=%04x irq=%i\n",
 540102                     __func__, pci_table[t].vendor_id,
 540103                     pci_table[t].device_id,
 540104                     pci_table[t].base_io, pci_table[t].irq);
 540105           // 
 540106           // Next PCI table row.
 540107           // 
 540108           t++;
 540109         }
 540110     }
 540111 }

94.4.29   kernel/driver/pci/pci_public.c

Si veda la sezione 93.19.

 550001 #include <kernel/driver/pci.h>
 550002 //----------------------------------------------------------
 550003 pci_t pci_table[PCI_MAX_DEVICES];
 550004 //----------------------------------------------------------

94.4.30   kernel/driver/screen.h

Si veda la sezione 93.22.

 560001 #ifndef _KERNEL_DRIVER_SCREEN_H
 560002 #define _KERNEL_DRIVER_SCREEN_H 1
 560003 //----------------------------------------------------------
 560004 #include <restrict.h>
 560005 #include <stdint.h>
 560006 //----------------------------------------------------------
 560007 // Virtual consoles data and VGA references.
 560008 //
 560009 #define SCREEN_MAX     4
 560010 #define SCREEN_ROWS    25
 560011 #define SCREEN_COLS    80
 560012 #define SCREEN_CELLS  (SCREEN_ROWS * SCREEN_COLS)
 560013 //
 560014 #define VGA_ATTR       0x07
 560015 #define VGA_ADDR       0xB8000
 560016 #define VGA_CELL      ((uint16_t *) VGA_ADDR)
 560017 //
 560018 typedef struct
 560019 {
 560020   uint16_t cell[SCREEN_CELLS];  // [1]
 560021   int position;
 560022 } screen_t;
 560023 //
 560024 // [1] Every character on the screen needs another
 560025 //     attribute byte.
 560026 //
 560027 //----------------------------------------------------------
 560028 extern int screen_active;
 560029 extern screen_t screen_table[];
 560030 //----------------------------------------------------------
 560031 int screen_clear (screen_t * screen);
 560032 screen_t *screen_current (void);
 560033 void screen_init (void);
 560034 int screen_new_line (screen_t * screen);
 560035 int screen_number (screen_t * screen);
 560036 screen_t *screen_pointer (int scrn);
 560037 int screen_putc (screen_t * screen, int c);
 560038 int screen_scroll (screen_t * screen);
 560039 int screen_select (screen_t * screen);
 560040 void screen_update (screen_t * screen);
 560041 //----------------------------------------------------------
 560042 #define screen_cell(c, attrib) \
 560043     ((uint16_t) c \
 560044      | ((((uint16_t) attrib) << 8) & 0xFF00))
 560045 //----------------------------------------------------------
 560046 #endif

94.4.31   kernel/driver/screen/screen_clear.c

Si veda la sezione 93.22.

 570001 #include <kernel/driver/screen.h>
 570002 #include <errno.h>
 570003 //----------------------------------------------------------
 570004 int
 570005 screen_clear (screen_t * screen)
 570006 {
 570007   int j;
 570008   // 
 570009   // Check argument.
 570010   // 
 570011   if (screen == NULL)
 570012     {
 570013       errset (EINVAL);
 570014       return (-1);
 570015     }
 570016   // 
 570017   // Clear the virtual screen.
 570018   // 
 570019   for (j = 0; j < SCREEN_CELLS; j++)
 570020     {
 570021       screen->cell[j] = screen_cell (' ', VGA_ATTR);
 570022     }
 570023   // 
 570024   // Place the cursor at the top.
 570025   // 
 570026   screen->position = 0;
 570027   // 
 570028   // Update the screen if it is the active one.
 570029   // 
 570030   screen_update (screen);
 570031   // 
 570032   // Ok.
 570033   // 
 570034   return (0);
 570035 }

94.4.32   kernel/driver/screen/screen_current.c

Si veda la sezione 93.22.

 580001 #include <kernel/driver/screen.h>
 580002 //----------------------------------------------------------
 580003 screen_t *
 580004 screen_current (void)
 580005 {
 580006   if (screen_active >= 0 && screen_active < SCREEN_MAX)
 580007     {
 580008       return &screen_table[screen_active];
 580009     }
 580010   else
 580011     {
 580012       return &screen_table[0];
 580013     }
 580014 }

94.4.33   kernel/driver/screen/screen_init.c

Si veda la sezione 93.22.

 590001 #include <kernel/driver/screen.h>
 590002 //----------------------------------------------------------
 590003 void
 590004 screen_init (void)
 590005 {
 590006   int i;
 590007   int j;
 590008   // 
 590009   // Reset and clear all virtual consoles.
 590010   // 
 590011   for (i = 0; i < SCREEN_MAX; i++)
 590012     {
 590013       // 
 590014       // Reset position.
 590015       // 
 590016       screen_table[i].position = 0;
 590017       // 
 590018       for (j = 0; j < SCREEN_CELLS; j++)
 590019         {
 590020           screen_table[i].cell[j] =
 590021             screen_cell (' ', VGA_ATTR);
 590022         }
 590023     }
 590024   // 
 590025   // Select the first screen.
 590026   // 
 590027   screen_active = 0;
 590028 }

94.4.34   kernel/driver/screen/screen_new_line.c

Si veda la sezione 93.22.

 600001 #include <kernel/driver/screen.h>
 600002 #include <errno.h>
 600003 //----------------------------------------------------------
 600004 int
 600005 screen_new_line (screen_t * screen)
 600006 {
 600007   int row;
 600008   // 
 600009   // Check argument.
 600010   // 
 600011   if (screen == NULL)
 600012     {
 600013       errset (EINVAL);
 600014       return (-1);
 600015     }
 600016   // 
 600017   // Find row position on screen.
 600018   // 
 600019   row = (screen->position / SCREEN_COLS);
 600020   // 
 600021   // We want to go one row down.
 600022   // 
 600023   row++;
 600024   // 
 600025   // Scroll the screen if necessary.
 600026   // 
 600027   for (; row >= SCREEN_ROWS; row--)
 600028     {
 600029       screen_scroll (screen);
 600030     }
 600031   // 
 600032   // Reset position at the beginning of the line.
 600033   // 
 600034   screen->position = row * SCREEN_COLS;
 600035   // 
 600036   // Update the video if it is the current one. This
 600037   // is necessary to
 600038   // update the cursor position, if the original
 600039   // column was not zero.
 600040   // 
 600041   screen_update (screen);
 600042   // 
 600043   // Ok.
 600044   // 
 600045   return (0);
 600046 }

94.4.35   kernel/driver/screen/screen_number.c

Si veda la sezione 93.22.

 610001 #include <kernel/driver/screen.h>
 610002 #include <stddef.h>
 610003 #include <errno.h>
 610004 #include <kernel/lib_k.h>
 610005 //----------------------------------------------------------
 610006 int
 610007 screen_number (screen_t * screen)
 610008 {
 610009   ptrdiff_t distance;
 610010   int n;
 610011   // 
 610012   if (screen == NULL)
 610013     {
 610014       errset (EINVAL);
 610015       return (-1);
 610016     }
 610017   // 
 610018   distance = (void *) screen - (void *) &screen_table[0];
 610019   // 
 610020   n = (distance % (sizeof (screen_t)));
 610021   // 
 610022   if (n != 0)
 610023     {
 610024       errset (EINVAL);  // Invalid pointer placement.
 610025       return (-1);
 610026     }
 610027   // 
 610028   n = (distance / (sizeof (screen_t)));
 610029   // 
 610030   if (n < 0 || n > SCREEN_MAX)
 610031     {
 610032       errset (EINVAL);  // Pointer outside the screen
 610033       // table.
 610034       return (-1);
 610035     }
 610036   // 
 610037   // If we are here, variable `n' holds the right
 610038   // screen number.
 610039   // 
 610040   return (n);
 610041 }

94.4.36   kernel/driver/screen/screen_pointer.c

Si veda la sezione 93.22.

 620001 #include <kernel/driver/screen.h>
 620002 #include <errno.h>
 620003 //----------------------------------------------------------
 620004 screen_t *
 620005 screen_pointer (int scrn)
 620006 {
 620007   if (scrn >= 0 && scrn < SCREEN_MAX)
 620008     {
 620009       return &screen_table[scrn];
 620010     }
 620011   else
 620012     {
 620013       errset (EINVAL);
 620014       return (NULL);
 620015     }
 620016 }

94.4.37   kernel/driver/screen/screen_public.c

Si veda la sezione 93.22.

 630001 #include <kernel/driver/screen.h>
 630002 #include <errno.h>
 630003 //----------------------------------------------------------
 630004 int screen_active;
 630005 screen_t screen_table[SCREEN_MAX];

94.4.38   kernel/driver/screen/screen_putc.c

Si veda la sezione 93.22.

 640001 #include <kernel/driver/screen.h>
 640002 #include <errno.h>
 640003 //----------------------------------------------------------
 640004 int
 640005 screen_putc (screen_t * screen, int c)
 640006 {
 640007   int row;
 640008   int col;
 640009   // 
 640010   if (screen == NULL)
 640011     {
 640012       errset (EINVAL);
 640013       return (-1);
 640014     }
 640015   // 
 640016   // Find row-col position on screen.
 640017   // 
 640018   row = (screen->position / SCREEN_COLS);
 640019   col = (screen->position - (row * SCREEN_COLS));
 640020   // 
 640021   // 
 640022   // 
 640023   if (c == '\n' || c == '\r')
 640024     {
 640025       screen_new_line (screen);
 640026       return (0);
 640027     }
 640028   else if (c == '\b')
 640029     {
 640030       screen->position--;
 640031       if (screen->position < 0)
 640032         {
 640033           screen->position = 0;
 640034         }
 640035       screen_update (screen);
 640036       return (0);
 640037     }
 640038   else if (screen->position == (SCREEN_CELLS - 1))
 640039     {
 640040       // 
 640041       // It is not a control character and we are
 640042       // already at the
 640043       // last cell of the last row.
 640044       // 
 640045       screen_scroll (screen);
 640046     }
 640047   // 
 640048   // If we are here, it is not a control character.
 640049   // So: print it.
 640050   // 
 640051   screen->cell[screen->position] =
 640052     screen_cell (c, VGA_ATTR);
 640053   screen->position++;
 640054   screen_update (screen);
 640055   // 
 640056   return (0);
 640057 }

94.4.39   kernel/driver/screen/screen_scroll.c

Si veda la sezione 93.22.

 650001 #include <kernel/driver/screen.h>
 650002 #include <errno.h>
 650003 //----------------------------------------------------------
 650004 int
 650005 screen_scroll (screen_t * screen)
 650006 {
 650007   int a;        // screen[].cell[] index.
 650008   int b;        // screen[].cell[] index
 650009   // 
 650010   // Check argument.
 650011   // 
 650012   if (screen == NULL)
 650013     {
 650014       errset (EINVAL);
 650015       return (-1);
 650016     }
 650017   // 
 650018   // Move up a line.
 650019   // 
 650020   for (a = 0, b = SCREEN_COLS; b < SCREEN_CELLS; a++, b++)
 650021     {
 650022       screen->cell[a] = screen->cell[b];
 650023     }
 650024   // 
 650025   // Clear last screen line.
 650026   // 
 650027   for (b = (SCREEN_CELLS - SCREEN_COLS);
 650028        b < SCREEN_CELLS; b++)
 650029     {
 650030       screen->cell[b] = screen_cell (' ', VGA_ATTR);
 650031     }
 650032   // 
 650033   // Update position.
 650034   // 
 650035   screen->position -= SCREEN_COLS;
 650036   if (screen->position < 0)
 650037     {
 650038       screen->position = 0;
 650039     }
 650040   // 
 650041   // Update the video if it is the current one.
 650042   // 
 650043   screen_update (screen);
 650044   // 
 650045   // Ok.
 650046   // 
 650047   return (0);
 650048 }

94.4.40   kernel/driver/screen/screen_select.c

Si veda la sezione 93.22.

 660001 #include <kernel/driver/screen.h>
 660002 #include <errno.h>
 660003 #include <kernel/ibm_i386.h>
 660004 //----------------------------------------------------------
 660005 int
 660006 screen_select (screen_t * screen)
 660007 {
 660008   int scrn;
 660009   // 
 660010   if (screen == NULL)
 660011     {
 660012       errset (EINVAL);
 660013       return (-1);
 660014     }
 660015   // 
 660016   // Get screen number.
 660017   // 
 660018   scrn = screen_number (screen);
 660019   if (scrn < 0)
 660020     {
 660021       errset (EINVAL);  // The screen pointer was
 660022       // invalid.
 660023       return (-1);
 660024     }
 660025   // 
 660026   // Set the current screen, update the screen memory
 660027   // and put the cursor.
 660028   // 
 660029   screen_active = scrn;
 660030   // 
 660031   screen_update (screen);
 660032   // 
 660033   // Ok.
 660034   // 
 660035   return (0);
 660036 }

94.4.41   kernel/driver/screen/screen_update.c

Si veda la sezione 93.22.

 670001 #include <kernel/driver/screen.h>
 670002 #include <kernel/ibm_i386.h>
 670003 #include <stddef.h>
 670004 //----------------------------------------------------------
 670005 void
 670006 screen_update (screen_t * screen)
 670007 {
 670008   screen_t *screen_showing;
 670009   int j;
 670010   unsigned char position_high;
 670011   unsigned char position_low;
 670012   // 
 670013   // Check input: if it is the NULL pointer, or it is
 670014   // not a valid
 670015   // pointer, then select the current screen.
 670016   // 
 670017   if ((screen == NULL) || (screen_number (screen) < 0))
 670018     {
 670019       screen = screen_current ();
 670020     }
 670021   // 
 670022   // Get current screen anyway.
 670023   // 
 670024   screen_showing = screen_current ();
 670025   // 
 670026   // Verify again to be in a valid screen.
 670027   // 
 670028   if (screen_number (screen_showing) < 0)
 670029     {
 670030       return;
 670031     }
 670032   // 
 670033   // If the selected screen is also the current
 670034   // screen, then
 670035   // must update the content (otherwise there is
 670036   // nothing to do).
 670037   // 
 670038   if (screen_showing == screen)
 670039     {
 670040       // 
 670041       // Copy virtual screen to real screen memory.
 670042       // 
 670043       for (j = 0; j < SCREEN_CELLS; j++)
 670044         {
 670045           VGA_CELL[j] = screen->cell[j];
 670046         }
 670047       // 
 670048       // Place the cursor.
 670049       // 
 670050       position_high =
 670051         (unsigned char) (screen->position >> 8);
 670052       position_low = (unsigned char) (screen->position);
 670053       // 
 670054       out_8 (0x3D4, 0x0E);
 670055       out_8 (0x3D5, position_high);
 670056       out_8 (0x3D4, 0x0F);
 670057       out_8 (0x3D5, position_low);
 670058     }
 670059 }

94.4.42   kernel/driver/tty.h

Si veda la sezione 93.24.

 680001 #ifndef _KERNEL_DRIVER_TTY_H
 680002 #define _KERNEL_DRIVER_TTY_H  1
 680003 //----------------------------------------------------------
 680004 #include <stddef.h>
 680005 #include <stdint.h>
 680006 #include <stdio.h>
 680007 #include <sys/types.h>
 680008 #include <kernel/ibm_i386.h>
 680009 #include <termios.h>
 680010 //----------------------------------------------------------
 680011 #define   TTYS_CONSOLE    4
 680012 #define   TTYS_SERIAL     0
 680013 #define   TTYS_TOTAL      (TTYS_CONSOLE + TTYS_SERIAL)
 680014 //----------------------------------------------------------
 680015 #define   TTY_INPUT_LINE_EDITING 0
 680016 #define   TTY_INPUT_LINE_CLOSED  1
 680017 //----------------------------------------------------------
 680018 typedef struct
 680019 {
 680020   dev_t device;
 680021   pid_t pgrp;   // Process group.
 680022   struct termios attr;  // termios attributes.
 680023   unsigned char status; // 0 = edit, 1 = end edit.
 680024   char line[MAX_CANON]; // Canonical input line.
 680025   int lpr;      // Input line position read.
 680026   int lpw;      // Input line position write.
 680027 } tty_t;
 680028 //----------------------------------------------------------
 680029 extern tty_t tty_table[TTYS_TOTAL];
 680030 //----------------------------------------------------------
 680031 tty_t *tty_reference (dev_t device);
 680032 dev_t tty_console (dev_t device);
 680033 int tty_read (dev_t device);
 680034 void tty_write (dev_t device, int c);
 680035 void tty_init (void);
 680036 //----------------------------------------------------------
 680037 #endif

94.4.43   kernel/driver/tty/tty_console.c

Si veda la sezione 93.24.

 690001 #include <sys/os32.h>
 690002 #include <kernel/driver/tty.h>
 690003 #include <kernel/driver/screen.h>
 690004 //----------------------------------------------------------
 690005 dev_t
 690006 tty_console (dev_t device)
 690007 {
 690008   static dev_t device_active = DEV_CONSOLE0;    // First
 690009   // time.
 690010   dev_t device_previous;
 690011   screen_t *screen;
 690012   // 
 690013   // Check if it required only the current device.
 690014   // 
 690015   if (device == 0)
 690016     {
 690017       return (device_active);
 690018     }
 690019   // 
 690020   // Fix if the device is not valid.
 690021   // 
 690022   if (device > DEV_CONSOLE3 || device < DEV_CONSOLE0)
 690023     {
 690024       device = DEV_CONSOLE0;
 690025     }
 690026   // 
 690027   // Update.
 690028   // 
 690029   device_previous = device_active;
 690030   device_active = device;
 690031   // 
 690032   // Get screen pointer.
 690033   // 
 690034   screen = screen_pointer ((int) (device_active & 0x00FF));
 690035   // 
 690036   // Switch.
 690037   // 
 690038   screen_select (screen);
 690039   // 
 690040   // Return previous device value.
 690041   // 
 690042   return (device_previous);
 690043 }

94.4.44   kernel/driver/tty/tty_init.c

Si veda la sezione 93.24.

 700001 #include <sys/os32.h>
 700002 #include <kernel/driver/tty.h>
 700003 #include <kernel/driver/screen.h>
 700004 #include <termios.h>
 700005 //----------------------------------------------------------
 700006 void
 700007 tty_init (void)
 700008 {
 700009   int page;     // console page.
 700010   // 
 700011   // Console initialization: console pages correspond
 700012   // to the first
 700013   // terminal items.
 700014   // 
 700015   for (page = 0; page < TTYS_CONSOLE; page++)
 700016     {
 700017       tty_table[page].device = DEV_CONSOLE0 + page;
 700018       tty_table[page].pgrp = 0;
 700019       tty_table[page].line[0] = 0;
 700020       tty_table[page].lpr = 0;
 700021       tty_table[page].lpw = 0;
 700022       tty_table[page].status = TTY_INPUT_LINE_EDITING;
 700023       // 
 700024       // Termios default configuration.
 700025       // 
 700026       tty_table[page].attr.c_iflag = BRKINT | ICRNL;
 700027       tty_table[page].attr.c_oflag = 0;
 700028       tty_table[page].attr.c_cflag = 0;
 700029       tty_table[page].attr.c_lflag =
 700030         ECHO | ECHOE | ECHOK | ECHONL | ICANON | ISIG;
 700031       // 
 700032       // VEOF == ASCII EOT
 700033       // 
 700034       tty_table[page].attr.c_cc[VEOF] = 0x04;
 700035       // 
 700036       // VEOL == undefined
 700037       // 
 700038       tty_table[page].attr.c_cc[VEOL] = 0x00;
 700039       // 
 700040       // VERASE == ASCII BS
 700041       // 
 700042       tty_table[page].attr.c_cc[VERASE] = 0x08;
 700043       // 
 700044       // VINTR == ASCII ETX
 700045       // 
 700046       tty_table[page].attr.c_cc[VINTR] = 0x03;
 700047       // 
 700048       // VKILL == undefined
 700049       // 
 700050       tty_table[page].attr.c_cc[VKILL] = 0x00;
 700051       // 
 700052       // VMIN == 0
 700053       // 
 700054       tty_table[page].attr.c_cc[VMIN] = 0x00;
 700055       // 
 700056       // VQUIT == ASCII FS
 700057       // 
 700058       tty_table[page].attr.c_cc[VQUIT] = 0x1C;
 700059       // 
 700060       // VSTART == undefined
 700061       // 
 700062       tty_table[page].attr.c_cc[VSTART] = 0x00;
 700063       // 
 700064       // VSUSP == undefined
 700065       // 
 700066       tty_table[page].attr.c_cc[VSUSP] = 0x00;
 700067       // 
 700068       // VTIME == 0
 700069       // 
 700070       tty_table[page].attr.c_cc[VTIME] = 0x00;
 700071     }
 700072   // 
 700073   // Set video mode.
 700074   // 
 700075   screen_init ();
 700076   // 
 700077   // Select the first console.
 700078   // 
 700079   tty_console (DEV_CONSOLE0);
 700080   // 
 700081   // Nothing else to configure (only consoles are
 700082   // available).
 700083   // 
 700084   return;
 700085 }

94.4.45   kernel/driver/tty/tty_public.c

Si veda la sezione 93.24.

 710001 #include <kernel/driver/tty.h>
 710002 //----------------------------------------------------------
 710003 tty_t tty_table[TTYS_TOTAL];

94.4.46   kernel/driver/tty/tty_read.c

Si veda la sezione 93.24.

 720001 #include <sys/os32.h>
 720002 #include <kernel/driver/tty.h>
 720003 #include <kernel/lib_k.h>
 720004 //----------------------------------------------------------
 720005 int
 720006 tty_read (dev_t device)
 720007 {
 720008   tty_t *tty;
 720009   int key;
 720010   // 
 720011   tty = tty_reference (device);
 720012   if (tty == NULL)
 720013     {
 720014       k_printf
 720015         ("kernel alert: cannot find terminal device "
 720016          "0x%08x!\n", (int) device);
 720017       // 
 720018       return (-1);
 720019     }
 720020   // 
 720021   // Read from canonical input line, but only if it is 
 720022   // time to read.
 720023   // 
 720024   if (tty->status == TTY_INPUT_LINE_CLOSED)
 720025     {
 720026       if (tty->lpr > tty->lpw)
 720027         {
 720028           // 
 720029           // There is nothing to read!
 720030           // Reset input line.
 720031           // 
 720032           tty->lpw = 0;
 720033           tty->lpr = 0;
 720034           tty->status = TTY_INPUT_LINE_EDITING;
 720035           // 
 720036           return (-1);
 720037         }
 720038       // 
 720039       // Read the key.
 720040       // 
 720041       key = tty->line[tty->lpr];
 720042       // 
 720043       // Move up the read cursor.
 720044       // 
 720045       tty->lpr++;
 720046     }
 720047   else
 720048     {
 720049       return (-1);
 720050     }
 720051   // 
 720052   // Return the key.
 720053   // 
 720054   return (key);
 720055 
 720056 }

94.4.47   kernel/driver/tty/tty_reference.c

Si veda la sezione 93.24.

 730001 #include <kernel/driver/tty.h>
 730002 //----------------------------------------------------------
 730003 tty_t *
 730004 tty_reference (dev_t device)
 730005 {
 730006   int t;        // Terminal index.
 730007   // 
 730008   // If device is zero, a reference to the whole table 
 730009   // is returned.
 730010   // 
 730011   if (device == 0)
 730012     {
 730013       return (tty_table);
 730014     }
 730015   // 
 730016   // Otherwise, a scan is made to find the selected
 730017   // device.
 730018   // 
 730019   for (t = 0; t < TTYS_TOTAL; t++)
 730020     {
 730021       if (tty_table[t].device == device)
 730022         {
 730023           // 
 730024           // Device found. Return the pointer.
 730025           // 
 730026           return (&tty_table[t]);
 730027         }
 730028     }
 730029   // 
 730030   // No device found!
 730031   // 
 730032   return (NULL);
 730033 }

94.4.48   kernel/driver/tty/tty_write.c

Si veda la sezione 93.24.

 740001 #include <sys/os32.h>
 740002 #include <kernel/driver/tty.h>
 740003 #include <kernel/driver/screen.h>
 740004 //----------------------------------------------------------
 740005 void
 740006 tty_write (dev_t device, int c)
 740007 {
 740008   screen_t *screen;
 740009   // 
 740010   if ((device & 0xFF00) == (DEV_CONSOLE_MAJOR << 8))
 740011     {
 740012       // 
 740013       // Get screen pointer.
 740014       // 
 740015       screen = screen_pointer ((int) (device & 0x00FF));
 740016       // 
 740017       screen_putc (screen, c);
 740018     }
 740019 }

94.5   os32: «kernel/fs.h»

Si veda la sezione 93.6.

 750001 #ifndef _KERNEL_FS_H
 750002 #define _KERNEL_FS_H 1
 750003 //----------------------------------------------------------
 750004 #include <stdint.h>
 750005 #include <sys/types.h>
 750006 #include <sys/stat.h>
 750007 #include <stdio.h>
 750008 #include <limits.h>
 750009 #include <kernel/memory.h>
 750010 #include <sys/socket.h>
 750011 #include <netinet/in.h>
 750012 #include <netinet/tcp.h>
 750013 #include <kernel/net/ip.h>
 750014 #include <kernel/net/tcp.h>
 750015 #include <sys/os32.h>
 750016 //----------------------------------------------------------
 750017 #define SB_MAX_INODE_BLOCKS    8        // 8*8192
 750018                                   // inodes max.
 750019 #define SB_MAX_ZONE_BLOCKS     8        // 8*8192
 750020                                   // data-zones
 750021                                   // max.
 750022 #define SB_BLOCK_SIZE       1024        // Fixed for
 750023                                   // Minix file
 750024                                   // system.
 750025 #define SB_MAX_ZONE_SIZE    4096        // log2 max is
 750026                                   // 1.
 750027 //----------------------------------------------------------
 750028 //
 750029 // blocks * (1024 * 8 / 16)
 750030 //   = number of bits, divided 16.
 750031 //
 750032 #define SB_MAP_INODE_SIZE   (SB_MAX_INODE_BLOCKS*512)
 750033 #define SB_MAP_ZONE_SIZE    (SB_MAX_ZONE_BLOCKS*512)
 750034 //----------------------------------------------------------
 750035 //
 750036 // Number of zone pointers contained inside a zone,
 750037 // used as an indirect inode list
 750038 // (a pointer = 16 bits = 2 bytes).
 750039 //
 750040 #define INODE_MAX_INDIRECT_ZONES  (SB_MAX_ZONE_SIZE/2)
 750041 //----------------------------------------------------------
 750042 #define INODE_MAX_REFERENCES      0xFF
 750043 //----------------------------------------------------------
 750044 typedef uint16_t zno_t; // Zone number.
 750045 //----------------------------------------------------------
 750046 // The structured type `inode_t' must be pre-declared
 750047 // here, because the type sb_t, described before the
 750048 // inode structure, has a member pointing to a type
 750049 // `inode_t'. So, must be declared previously the type
 750050 // `inode_t' as made of a type `struct inode', then the
 750051 // structure `inode' can be described. But for a matter
 750052 // of coherence, all other structured data declared
 750053 // inside this file follow the same procedure.
 750054 //
 750055 typedef struct sb sb_t;
 750056 typedef struct inode inode_t;
 750057 typedef struct sock sock_t;
 750058 typedef struct file file_t;
 750059 typedef struct fd fd_t;
 750060 typedef struct directory directory_t;
 750061 //----------------------------------------------------------
 750062 #define SB_MAX_SLOTS  16        // Handle max 16 file
 750063                                 // systems.
 750064 
 750065 struct sb
 750066 {       // File system super block:
 750067   uint16_t inodes;      // inodes available;
 750068   uint16_t zones;       // zones available (disk
 750069   // size);
 750070   uint16_t map_inode_blocks;    // inode bit map
 750071   // blocks;
 750072   uint16_t map_zone_blocks;     // data-zone bit map
 750073   // blocks;
 750074   uint16_t first_data_zone;     // first data-zone;
 750075   uint16_t log2_size_zone;      // log_2
 750076   // (size_zone/block_size);
 750077   uint32_t max_file_size;       // max file size in
 750078   // bytes;
 750079   uint16_t magic_number;        // file system magic
 750080   // number.
 750081   // -------------------------------------------------
 750082   // Extra management data, not saved inside the file
 750083   // system
 750084   // super block.
 750085   // -------------------------------------------------
 750086   dev_t device; // FS device [3]
 750087   inode_t *inode_mounted_on;    // [4]
 750088   blksize_t blksize;    // Calculated zone size.
 750089   int options;  // [5]
 750090   uint16_t map_inode[SB_MAP_INODE_SIZE];
 750091   uint16_t map_zone[SB_MAP_ZONE_SIZE];
 750092   char changed;
 750093 };
 750094 
 750095 extern sb_t sb_table[SB_MAX_SLOTS];
 750096 //
 750097 // [3] the member `device' must be kept at the same
 750098 //     position, because it is used to calculate the
 750099 //     super block header size, saved on disk.
 750100 //
 750101 // [4] If this pointer is not NULL, the super block is
 750102 //     related to a device mounted on a directory. The
 750103 //     inode of such directory is recorded here. Please
 750104 //     note that it is type `void *', instead of type
 750105 //     `inode_t', because type `inode_t' is declared
 750106 //     after type `sb_t'.
 750107 //     Please note that the type `sb_t' is declared
 750108 //     before the type `inode_t', but this member
 750109 //     points to a type `inode_t'.
 750110 //     This is the reason because it was necessary to
 750111 //     declare first the type `inode_t' as made of
 750112 //     `struct inode', to be described later. For
 750113 //     coherence, all derived type made of structured
 750114 //     data, are first declared as structure, and then,
 750115 //     later, described.
 750116 //
 750117 // [5] Mount options can be only `MOUNT_DEFAULT' or
 750118 //     `MOUNT_RO', as defined inside file
 750119 //     `lib/sys/os32.h'.
 750120 //
 750121 //----------------------------------------------------------
 750122 #define INODE_MAX_SLOTS         (32 * OPEN_MAX)
 750123 #define INODE_PIPE_BUFFER_SIZE  18      // (7 dir. + 2
 750124                                       // ind.) * 2.
 750125 //
 750126 struct inode
 750127 {       // Inode (32 byte total):
 750128   uint16_t mode;        // file type and permissions;
 750129   uint16_t uid; // user ID (16 bit);
 750130   uint32_t size;        // file size in bytes;
 750131   uint32_t time;        // file data modification
 750132   // time;
 750133   uint8_t gid;  // group ID (8 bit);
 750134   uint8_t links;        // links to the inode;
 750135   uint16_t direct[7];   // direct zones;
 750136   uint16_t indirect1;   // indirect zones;
 750137   uint16_t indirect2;   // double indirect zones.
 750138   // -------------------------------------------------
 750139   // Extra management data, not saved inside the disk
 750140   // file system.
 750141   // -------------------------------------------------
 750142   sb_t *sb;     // Inode's super block. [7]
 750143   ino_t ino;    // Inode number.
 750144   sb_t *sb_attached;    // [8]
 750145   blkcnt_t blkcnt;      // Rounded size/blksize.
 750146   unsigned char references;     // Run time active
 750147   // references.
 750148   char changed:1,       // 1 == to be saved.
 750149     pipe_dir:1; // 0 == read, 1 == write.
 750150   unsigned char pipe_off_read;  // Pipe read offset.
 750151   unsigned char pipe_off_write; // Pipe write offset 
 750152   unsigned char pipe_ref_read;  // Pipe read
 750153   // references.
 750154   unsigned char pipe_ref_write; // Pipe write
 750155   // references 
 750156 };
 750157 
 750158 extern inode_t inode_table[INODE_MAX_SLOTS];
 750159 //
 750160 // [7] the member `sb' must be kept at the same
 750161 //     position, because it is used to calculate the
 750162 //     inode header size, saved on disk.
 750163 //
 750164 // [8] If the inode is a mount point for another
 750165 //     device, the other super block pointer is saved
 750166 //     inside `sb_attached'.
 750167 //
 750168 //----------------------------------------------------------
 750169 #define SOCK_MAX_SLOTS          64
 750170 #define SOCK_MAX_QUEUE          (SOCK_MAX_SLOTS/4)
 750171 //
 750172 struct sock
 750173 {
 750174   int family;
 750175   int type;
 750176   int protocol;
 750177   h_addr_t laddr;       // Local address, host byte
 750178   // order.
 750179   h_port_t lport;       // Local port, host byte
 750180   // order.
 750181   h_addr_t raddr;       // Remote address, host byte
 750182   // order.
 750183   h_port_t rport;       // Remote port, host byte
 750184   // order.
 750185   struct
 750186   {
 750187     clock_t clock[IP_MAX_PACKETS];      // [9]
 750188   } read;
 750189   uint8_t active:1,     // Is the socket used?
 750190     unreach_net:1,      // 
 750191     unreach_host:1,     // ICMP unreachable status.
 750192     unreach_prot:1,     // 
 750193     unreach_port:1;     // 
 750194   struct
 750195   {
 750196     uint16_t conn:4,    // Connection status.
 750197       can_write:1,      // Can write to send_data[].
 750198       can_read:1,       // Can read from *recv_index.
 750199       can_send:1,       // Can send data.
 750200       can_recv:1,       // Can receive data.
 750201       send_closed:1,    // Closed send direction.
 750202       recv_closed:1;    // Closed receive direction.
 750203     // 
 750204     uint32_t lsq[16];   // Local sequence array.
 750205     uint32_t lsq_ack;   // Expected acknowledge.
 750206     uint32_t rsq[16];   // Remote sequence array.
 750207     uint8_t lsqi:4,     // Local sequence array index.
 750208       rsqi:4;   // Remote sequence array index.
 750209     // 
 750210     clock_t clock;      // When was last send.
 750211     // 
 750212     uint8_t send_data[TCP_MSS - sizeof (struct tcphdr)];
 750213     size_t send_size;   // Size of `send_data[]'
 750214     // content.
 750215     int send_flags;
 750216     uint8_t recv_data[TCP_MAX_DATA_SIZE];       // Data 
 750217     // received.
 750218     size_t recv_size;   // Size of `recv_data[]'
 750219     // content.
 750220     uint8_t *recv_index;        // Read index inside
 750221     // `recv_data[]'.
 750222     pid_t listen_pid;   // Process listening at local
 750223     // port.
 750224     int listen_max;     // Max connection requests.
 750225     int listen_queue[SOCK_MAX_QUEUE];   // [10]
 750226   } tcp;
 750227 };
 750228 //
 750229 extern sock_t sock_table[SOCK_MAX_SLOTS];
 750230 //
 750231 // [9] The array `read.clock[]' has the same size as
 750232 //     the array as `ip_tables[]', so that it can be
 750233 //     saved, inside the former, the clock time of a
 750234 //     packet read for the socket purposes.
 750235 //     This is necessary to know if the packet was
 750236 //     already managed inside the socket system, or
 750237 //     it is new.
 750238 //
 750239 // [10] When a process listen o a local port, member
 750240 //      `listen_pid' contains the pid number; member
 750241 //      `listen_max' contains the max allowed
 750242 //      connections that will be serviced; the array
 750243 //      `listen_queue[]' will contain the file
 750244 //      descriptors of established connections.
 750245 //      If `listen_queue[x]' is equal to -1, it means
 750246 //      that there is no file descriptor there.
 750247 //
 750248 //----------------------------------------------------------
 750249 #define FILE_MAX_SLOTS             (64 * OPEN_MAX)
 750250 
 750251 struct file
 750252 {
 750253   int references;
 750254   off_t offset; // File position.
 750255   int oflags;   // Open mode: r/w/r+w [11]
 750256   inode_t *inode;
 750257   sock_t *sock;
 750258 };
 750259 
 750260 extern file_t file_table[FILE_MAX_SLOTS];
 750261 //
 750262 // [11] the member `oflags' can get only O_RDONLY,
 750263 //      O_WRONLY, O_RDWR, (from header `fcntl.h')
 750264 //      combined with OR binary operator.
 750265 //
 750266 //----------------------------------------------------------
 750267 struct fd
 750268 {
 750269   int fl_flags; // File status flags and file
 750270   // access modes. [12]
 750271   int fd_flags; // File descriptor flags:
 750272   // currently only FD_CLOEXEC.
 750273   file_t *file; // Pointer to the file table.
 750274 };
 750275 //
 750276 // [12] the member `fl_flags' can get only O_RDONLY,
 750277 //      O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NOCTTY,
 750278 //      O_TRUNC, O_APPEND and O_NONBLOCK
 750279 //      (from header `fcntl.h') combined with OR
 750280 //      binary operator.
 750281 //      Options like O_DSYNC, O_RSYNC and O_SYNC are
 750282 //      not taken into consideration by os32.
 750283 //
 750284 //  Please notice that each process has its own `fd'
 750285 //  table, embedded inside the process table.
 750286 //----------------------------------------------------------
 750287 struct directory
 750288 {       // Directory entry:
 750289   uint16_t ino; // inode number;
 750290   char name[NAME_MAX];  // file name.
 750291 };
 750292 //----------------------------------------------------------
 750293 void fs_init (void);
 750294 //----------------------------------------------------------
 750295 int sb_inode_status (sb_t * sb, ino_t ino);
 750296 sb_t *sb_mount (dev_t device, inode_t ** inode_mnt,
 750297                 int options);
 750298 void sb_print (void);
 750299 sb_t *sb_reference (dev_t device);
 750300 int sb_save (sb_t * sb);
 750301 int sb_zone_status (sb_t * sb, zno_t zone);
 750302 //----------------------------------------------------------
 750303 zno_t zone_alloc (sb_t * sb);
 750304 int zone_free (sb_t * sb, zno_t zone);
 750305 void zone_print (sb_t * sb, zno_t zone);
 750306 int zone_read (sb_t * sb, zno_t zone, void *buffer);
 750307 int zone_write (sb_t * sb, zno_t zone, void *buffer);
 750308 //----------------------------------------------------------
 750309 inode_t *inode_alloc (dev_t device, mode_t mode,
 750310                       uid_t uid, gid_t gid);
 750311 int inode_check (inode_t * inode, mode_t type,
 750312                  int perm, uid_t uid, gid_t gid);
 750313 int inode_dir_empty (inode_t * inode);
 750314 ssize_t inode_file_read (inode_t * inode, off_t offset,
 750315                          void *buffer, size_t count,
 750316                          int *eof);
 750317 ssize_t inode_file_write (inode_t * inode,
 750318                           off_t offset,
 750319                           const void *buffer, size_t count);
 750320 int inode_free (inode_t * inode);
 750321 blkcnt_t inode_fzones_read (inode_t * inode,
 750322                             zno_t zone_start,
 750323                             void *buffer, blkcnt_t blkcnt);
 750324 blkcnt_t inode_fzones_write (inode_t * inode,
 750325                              zno_t zone_start,
 750326                              void *buffer, blkcnt_t blkcnt);
 750327 inode_t *inode_get (dev_t device, ino_t ino);
 750328 inode_t *inode_pipe_make (void);
 750329 ssize_t inode_pipe_read (inode_t * inode, void *buffer,
 750330                          size_t count, int *eof);
 750331 ssize_t inode_pipe_write (inode_t * inode,
 750332                           const void *buffer, size_t count);
 750333 void inode_print (void);
 750334 int inode_put (inode_t * inode);
 750335 inode_t *inode_reference (dev_t device, ino_t ino);
 750336 int inode_save (inode_t * inode);
 750337 inode_t *inode_stdio_dev_make (dev_t device, mode_t mode);
 750338 int inode_truncate (inode_t * inode);
 750339 zno_t inode_zone (inode_t * inode, zno_t fzone, int write);
 750340 //----------------------------------------------------------
 750341 file_t *file_pipe_make (void);
 750342 file_t *file_reference (int fno);
 750343 file_t *file_stdio_dev_make (dev_t device, mode_t mode,
 750344                              int oflags);
 750345 //----------------------------------------------------------
 750346 dev_t path_device (pid_t pid, const char *path);
 750347 int path_fix (char *path);
 750348 int path_full (const char *path,
 750349                const char *path_cwd, char *full_path);
 750350 inode_t *path_inode (pid_t pid, const char *path);
 750351 inode_t *path_inode_link (pid_t pid, const char *path,
 750352                           inode_t * inode, mode_t mode);
 750353 //----------------------------------------------------------
 750354 int fd_dup (pid_t pid, int fdn_old, int fdn_min);
 750355 fd_t *fd_reference (pid_t pid, int *fdn);
 750356 //----------------------------------------------------------
 750357 //
 750358 // void  sock_put (sock_t *s);
 750359 //
 750360 #define  sock_put(s)  (s->active=0)
 750361 
 750362 sock_t *sock_reference (int skn);
 750363 h_port_t sock_free_port (void);
 750364 //----------------------------------------------------------
 750365 
 750366 #endif

94.5.1   kernel/fs/fd_dup.c

Si veda la sezione 93.6.1.

 760001 #include <kernel/proc.h>
 760002 #include <kernel/fs.h>
 760003 #include <errno.h>
 760004 #include <fcntl.h>
 760005 //----------------------------------------------------------
 760006 int
 760007 fd_dup (pid_t pid, int fdn_old, int fdn_min)
 760008 {
 760009   proc_t *ps;
 760010   int fdn_new;
 760011   // 
 760012   // Verify argument.
 760013   // 
 760014   if (fdn_min < 0 || fdn_min >= OPEN_MAX)
 760015     {
 760016       errset (EINVAL);  // Invalid argument.
 760017       return (-1);
 760018     }
 760019   // 
 760020   // Get process.
 760021   // 
 760022   ps = proc_reference (pid);
 760023   // 
 760024   // Verify if `fdn_old' is a valid value.
 760025   // 
 760026   if (fdn_old < 0 ||
 760027       fdn_old >= OPEN_MAX || ps->fd[fdn_old].file == NULL)
 760028     {
 760029       errset (EBADF);   // Bad file descriptor.
 760030       return (-1);
 760031     }
 760032   // 
 760033   // Find the first free slot and duplicate the file
 760034   // descriptor.
 760035   // 
 760036   for (fdn_new = fdn_min; fdn_new < OPEN_MAX; fdn_new++)
 760037     {
 760038       if (ps->fd[fdn_new].file == NULL)
 760039         {
 760040           ps->fd[fdn_new].fl_flags =
 760041             ps->fd[fdn_old].fl_flags;
 760042           ps->fd[fdn_new].fd_flags =
 760043             ps->fd[fdn_old].fd_flags & ~FD_CLOEXEC;
 760044           ps->fd[fdn_new].file = ps->fd[fdn_old].file;
 760045           ps->fd[fdn_new].file->references++;
 760046           return (fdn_new);
 760047         }
 760048     }
 760049   // 
 760050   // No fd slot available.
 760051   // 
 760052   errset (EMFILE);      // Too many open files.
 760053   return (-1);
 760054 }

94.5.2   kernel/fs/fd_reference.c

Si veda la sezione 93.6.2.

 770001 #include <kernel/proc.h>
 770002 #include <kernel/lib_k.h>
 770003 #include <errno.h>
 770004 //----------------------------------------------------------
 770005 fd_t *
 770006 fd_reference (pid_t pid, int *fdn)
 770007 {
 770008   proc_t *ps;
 770009   // 
 770010   // Get process.
 770011   // 
 770012   ps = proc_reference (pid);
 770013   // 
 770014   // See what to do.
 770015   // 
 770016   if (*fdn < 0)
 770017     {
 770018       // 
 770019       // Find the first free slot.
 770020       // 
 770021       for (*fdn = 0; *fdn < OPEN_MAX; (*fdn)++)
 770022         {
 770023           if (ps->fd[*fdn].file == NULL)
 770024             {
 770025               return (&(ps->fd[*fdn]));
 770026             }
 770027         }
 770028       *fdn = -1;
 770029       return (NULL);
 770030     }
 770031   else
 770032     {
 770033       if (*fdn < OPEN_MAX)
 770034         {
 770035           // 
 770036           // Might return even a free file descriptor.
 770037           // 
 770038           return (&(ps->fd[*fdn]));
 770039         }
 770040       else
 770041         {
 770042           return (NULL);
 770043         }
 770044     }
 770045 }

94.5.3   kernel/fs/file_pipe_make.c

Si veda la sezione 93.6.4.

 780001 #include <kernel/proc.h>
 780002 #include <errno.h>
 780003 #include <fcntl.h>
 780004 //----------------------------------------------------------
 780005 file_t *
 780006 file_pipe_make (void)
 780007 {
 780008   inode_t *inode;
 780009   file_t *file;
 780010   // 
 780011   // Try to allocate a device inode.
 780012   // 
 780013   inode = inode_pipe_make ();
 780014   if (inode == NULL)
 780015     {
 780016       // 
 780017       // Variable `errno' is already set by
 780018       // `inode_stdio_dev_make()'.
 780019       // 
 780020       errset (errno);
 780021       return (NULL);
 780022     }
 780023   // 
 780024   // Inode allocated: need to allocate the system file 
 780025   // item.
 780026   // 
 780027   file = file_reference (-1);
 780028   if (file == NULL)
 780029     {
 780030       // 
 780031       // Remove the inode and return an error.
 780032       // 
 780033       inode_put (inode);
 780034       errset (ENFILE);  // Too many files open in
 780035       // system.
 780036       return (NULL);
 780037     }
 780038   // 
 780039   // Fill with data the system file item.
 780040   // 
 780041   file->references = 2;
 780042   file->oflags = (O_RDONLY | O_WRONLY);
 780043   file->inode = inode;
 780044   // 
 780045   // Return system file pointer.
 780046   // 
 780047   return (file);
 780048 }

94.5.4   kernel/fs/file_reference.c

Si veda la sezione 93.6.5.

 790001 #include <kernel/proc.h>
 790002 #include <errno.h>
 790003 #include <fcntl.h>
 790004 //----------------------------------------------------------
 790005 file_t *
 790006 file_reference (int fno)
 790007 {
 790008   // 
 790009   // Check type of request.
 790010   // 
 790011   if (fno < 0)
 790012     {
 790013       // 
 790014       // Find a free slot.
 790015       // 
 790016       for (fno = 0; fno < FILE_MAX_SLOTS; fno++)
 790017         {
 790018           if (file_table[fno].references <= 0)
 790019             {
 790020               return (&file_table[fno]);
 790021             }
 790022         }
 790023       return (NULL);
 790024     }
 790025   else if (fno > FILE_MAX_SLOTS)
 790026     {
 790027       return (NULL);
 790028     }
 790029   else
 790030     {
 790031       return (&file_table[fno]);
 790032     }
 790033 }

94.5.5   kernel/fs/file_stdio_dev_make.c

Si veda la sezione 93.6.6.

 800001 #include <kernel/proc.h>
 800002 #include <errno.h>
 800003 #include <fcntl.h>
 800004 //----------------------------------------------------------
 800005 file_t *
 800006 file_stdio_dev_make (dev_t device, mode_t mode, int oflags)
 800007 {
 800008   inode_t *inode;
 800009   file_t *file;
 800010   // 
 800011   // Try to allocate a device inode.
 800012   // 
 800013   inode = inode_stdio_dev_make (device, mode);
 800014   if (inode == NULL)
 800015     {
 800016       // 
 800017       // Variable `errno' is already set by
 800018       // `inode_stdio_dev_make()'.
 800019       // 
 800020       errset (errno);
 800021       return (NULL);
 800022     }
 800023   // 
 800024   // Inode allocated: need to allocate the system file 
 800025   // item.
 800026   // 
 800027   file = file_reference (-1);
 800028   if (file == NULL)
 800029     {
 800030       // 
 800031       // Remove the inode and return an error.
 800032       // 
 800033       inode_put (inode);
 800034       errset (ENFILE);  // Too many files open in
 800035       // system.
 800036       return (NULL);
 800037     }
 800038   // 
 800039   // Fill with data the system file item.
 800040   // 
 800041   file->references = 1;
 800042   file->oflags = (oflags & (O_RDONLY | O_WRONLY));
 800043   file->inode = inode;
 800044   // 
 800045   // Return system file pointer.
 800046   // 
 800047   return (file);
 800048 }

94.5.6   kernel/fs/fs_init.c

Si veda la sezione 93.6.3.

 810001 #include <kernel/fs.h>
 810002 #include <string.h>
 810003 //----------------------------------------------------------
 810004 void
 810005 fs_init (void)
 810006 {
 810007   int s;
 810008   int i;
 810009   int f;
 810010   // 
 810011   for (s = 0; s < SB_MAX_SLOTS; s++)
 810012     {
 810013       sb_table[s].device = 0;
 810014       sb_table[s].inode_mounted_on = NULL;
 810015     }
 810016   // 
 810017   for (i = 0; i < INODE_MAX_SLOTS; i++)
 810018     {
 810019       inode_table[i].references = 0;
 810020     }
 810021   // 
 810022   for (f = 0; f < FILE_MAX_SLOTS; f++)
 810023     {
 810024       file_table[f].references = 0;
 810025       file_table[f].inode = NULL;
 810026       file_table[f].sock = NULL;
 810027     }
 810028   // 
 810029   // Reset the socket table with 0x00.
 810030   // 
 810031   memset (sock_table, 0x00, sizeof (sock_table));
 810032 }

94.5.7   kernel/fs/fs_public.c

Si veda la sezione 93.6.

 820001 #include <kernel/fs.h>
 820002 //----------------------------------------------------------
 820003 sb_t sb_table[SB_MAX_SLOTS];
 820004 file_t file_table[FILE_MAX_SLOTS];
 820005 inode_t inode_table[INODE_MAX_SLOTS];
 820006 sock_t sock_table[SOCK_MAX_SLOTS];
 820007 //----------------------------------------------------------

94.5.8   kernel/fs/inode_alloc.c

Si veda la sezione 93.6.7.

 830001 #include <kernel/fs.h>
 830002 #include <errno.h>
 830003 #include <kernel/lib_k.h>
 830004 #include <kernel/lib_s.h>
 830005 //----------------------------------------------------------
 830006 inode_t *
 830007 inode_alloc (dev_t device, mode_t mode, uid_t uid,
 830008              gid_t gid)
 830009 {
 830010   sb_t *sb;
 830011   inode_t *inode;
 830012   int m;        // Index inside the inode map.
 830013   int map_element;
 830014   int map_bit;
 830015   int map_mask;
 830016   ino_t ino;
 830017   // 
 830018   // Check for arguments.
 830019   // 
 830020   if (mode == 0)
 830021     {
 830022       errset (EINVAL);  // Invalid argument.
 830023       return (NULL);
 830024     }
 830025   // 
 830026   // Get the super block from the known device.
 830027   // 
 830028   sb = sb_reference (device);
 830029   if (sb == NULL)
 830030     {
 830031       errset (ENODEV);  // No such device.
 830032       return (NULL);
 830033     }
 830034   // 
 830035   // Find a free inode.
 830036   // 
 830037   while (1)
 830038     {
 830039       // 
 830040       // Scan the inode bit map, to find a free inode
 830041       // for new allocation.
 830042       // 
 830043       for (m = 0; m < (SB_MAP_INODE_SIZE * 16); m++)
 830044         {
 830045           map_element = m / 16;
 830046           map_bit = m % 16;
 830047           map_mask = 1 << map_bit;
 830048           if (!(sb->map_inode[map_element] & map_mask))
 830049             {
 830050               // 
 830051               // Found a free element: change the map
 830052               // to
 830053               // allocate the inode.
 830054               // 
 830055               sb->map_inode[map_element] |= map_mask;
 830056               sb->changed = 1;
 830057               ino = m;  // Found a free inode:
 830058               break;    // exit the scan loop.
 830059             }
 830060         }
 830061       // 
 830062       // Check if the scan was successful.
 830063       // 
 830064       if (ino == 0)
 830065         {
 830066           errset (ENOSPC);      // No space left on
 830067           // device.
 830068           return (NULL);
 830069         }
 830070       // 
 830071       // The inode was allocated inside the map in
 830072       // memory.
 830073       // 
 830074       inode = inode_get (device, ino);
 830075       if (inode == NULL)
 830076         {
 830077           errset (ENFILE);      // Too many files open 
 830078           // in system.
 830079           return (NULL);
 830080         }
 830081       // 
 830082       // Verify if the inode is really free: if it
 830083       // isn't, must save
 830084       // it to disk.
 830085       // 
 830086       if (inode->size > 0 || inode->links > 0)
 830087         {
 830088           // 
 830089           // Strange: should not have a size! Check if 
 830090           // there are even
 830091           // links. Please note that 255 links (that
 830092           // is -1) is to be
 830093           // considered a free inode, marked in a
 830094           // special way for some
 830095           // unknown reason. Currently, `LINK_MAX' is
 830096           // equal to 254,
 830097           // for that reason.
 830098           // 
 830099           if (inode->links > 0 && inode->links < LINK_MAX)
 830100             {
 830101               // 
 830102               // Tell something.
 830103               // 
 830104               k_printf ("kernel alert: device %04x: "
 830105                         "found \"free\" inode %i "
 830106                         "that still has size %i "
 830107                         "and %i links!\n",
 830108                         device, ino, inode->size,
 830109                         inode->links);
 830110               // 
 830111               // The inode must be set again to free,
 830112               // inside
 830113               // the bit map.
 830114               // 
 830115               map_element = ino / 16;
 830116               map_bit = ino % 16;
 830117               map_mask = 1 << map_bit;
 830118               sb->map_inode[map_element] &= ~map_mask;
 830119               sb->changed = 1;
 830120               // 
 830121               // Try to fix: reset all to zero.
 830122               // 
 830123               inode->mode = 0;
 830124               inode->uid = 0;
 830125               inode->gid = 0;
 830126               inode->time = 0;
 830127               inode->links = 0;
 830128               inode->size = 0;
 830129               inode->direct[0] = 0;
 830130               inode->direct[1] = 0;
 830131               inode->direct[2] = 0;
 830132               inode->direct[3] = 0;
 830133               inode->direct[4] = 0;
 830134               inode->direct[5] = 0;
 830135               inode->direct[6] = 0;
 830136               inode->indirect1 = 0;
 830137               inode->indirect2 = 0;
 830138               inode->changed = 1;
 830139               // 
 830140               // Save fixed inode to disk.
 830141               // 
 830142               inode_put (inode);
 830143               continue;
 830144             }
 830145           else
 830146             {
 830147               // 
 830148               // Truncate the inode, save and break.
 830149               // 
 830150               inode_truncate (inode);
 830151               inode_save (inode);
 830152               break;
 830153             }
 830154         }
 830155       else
 830156         {
 830157           // 
 830158           // Considering free the inode found.
 830159           // 
 830160           break;
 830161         }
 830162     }
 830163   // 
 830164   // Put data inside the inode.
 830165   // 
 830166   inode->mode = mode;
 830167   inode->uid = uid;
 830168   inode->gid = gid;
 830169   inode->size = 0;
 830170   inode->time = s_time ((pid_t) 0, NULL);
 830171   inode->links = 0;
 830172   inode->changed = 1;
 830173   // 
 830174   // Save the inode.
 830175   // 
 830176   inode_save (inode);
 830177   // 
 830178   // Return the inode pointer.
 830179   // 
 830180   return (inode);
 830181 }

94.5.9   kernel/fs/inode_check.c

Si veda la sezione 93.6.8.

 840001 #include <kernel/fs.h>
 840002 #include <errno.h>
 840003 #include <kernel/lib_k.h>
 840004 //----------------------------------------------------------
 840005 int
 840006 inode_check (inode_t * inode, mode_t type, int perm,
 840007              uid_t uid, gid_t gid)
 840008 {
 840009   // 
 840010   // Ensure that the variable `type' has only the
 840011   // requested file type.
 840012   // 
 840013   type = (type & S_IFMT);
 840014   // 
 840015   // Check inode argument.
 840016   // 
 840017   if (inode == NULL)
 840018     {
 840019       errset (EINVAL);  // Invalid argument.
 840020       return (-1);
 840021     }
 840022   // 
 840023   // The inode is not NULL: verify that the inode is
 840024   // of a type
 840025   // allowed (the parameter `type' can hold more than
 840026   // one
 840027   // possibility).
 840028   // 
 840029   if (!(inode->mode & type))
 840030     {
 840031       errset (E_FILE_TYPE);     // The file type is
 840032       // not
 840033       return (-1);      // the expected one.
 840034     }
 840035   // 
 840036   // The file type is correct.
 840037   // 
 840038   if (inode->uid != 0 && uid == 0)
 840039     {
 840040       return (0);       // The root user has all
 840041       // permissions.
 840042     }
 840043   // 
 840044   // The user is not root or the inode is owned by
 840045   // root.
 840046   // 
 840047   if (inode->uid == uid)
 840048     {
 840049       // 
 840050       // The user own the inode and must check user
 840051       // permissions.
 840052       // 
 840053       perm = (perm << 6);
 840054       if ((inode->mode & perm) ^ perm)
 840055         {
 840056           errset (EACCES);      // Permission denied.
 840057           return (-1);
 840058         }
 840059       else
 840060         {
 840061           return (0);
 840062         }
 840063     }
 840064   // 
 840065   // The user does not own the inode: the group
 840066   // permissions are
 840067   // checked.
 840068   // 
 840069   if (inode->gid == gid)
 840070     {
 840071       // 
 840072       // The group own the inode and must check user
 840073       // permissions.
 840074       // 
 840075       perm = (perm << 3);
 840076       if ((inode->mode & perm) ^ perm)
 840077         {
 840078           errset (EACCES);      // Permission denied.
 840079           return (-1);
 840080         }
 840081       else
 840082         {
 840083           return (0);
 840084         }
 840085     }
 840086   // 
 840087   // The user and the group do not own the inode: the
 840088   // other
 840089   // permissions are checked.
 840090   // 
 840091   if ((inode->mode & perm) ^ perm)
 840092     {
 840093       errset (EACCES);  // Permission denied.
 840094       return (-1);
 840095     }
 840096   else
 840097     {
 840098       return (0);
 840099     }
 840100 }

94.5.10   kernel/fs/inode_dir_empty.c

Si veda la sezione 93.6.9.

 850001 #include <kernel/fs.h>
 850002 #include <errno.h>
 850003 #include <kernel/lib_k.h>
 850004 //----------------------------------------------------------
 850005 int
 850006 inode_dir_empty (inode_t * inode)
 850007 {
 850008   off_t start;
 850009   char buffer[SB_MAX_ZONE_SIZE];
 850010   directory_t *dir;
 850011   ssize_t size_read;
 850012   int d;        // Directory buffer index.
 850013   // 
 850014   // Check argument: must be a directory.
 850015   // 
 850016   if (inode == NULL || !S_ISDIR (inode->mode))
 850017     {
 850018       errset (EINVAL);  // Invalid argument.
 850019       return (0);       // false
 850020     }
 850021   // 
 850022   // Read the directory content: if an item is present 
 850023   // (except `.' and
 850024   // `..'), the directory is not empty.
 850025   // 
 850026   for (start = 0;
 850027        start < inode->size; start += inode->sb->blksize)
 850028     {
 850029       size_read =
 850030         inode_file_read (inode, start, buffer,
 850031                          inode->sb->blksize, NULL);
 850032       if (size_read < sizeof (directory_t))
 850033         {
 850034           break;
 850035         }
 850036       // 
 850037       // Scan the directory portion just read.
 850038       // 
 850039       dir = (directory_t *) buffer;
 850040       // 
 850041       for (d = 0; d < size_read;
 850042            d += (sizeof (directory_t)), dir++)
 850043         {
 850044           if (dir->ino != 0 &&
 850045               strncmp (dir->name, ".", NAME_MAX) != 0
 850046               && strncmp (dir->name, "..", NAME_MAX) != 0)
 850047             {
 850048               // 
 850049               // There is an item and the directory is 
 850050               // not empty.
 850051               // 
 850052               return (0);       // false
 850053             }
 850054         }
 850055     }
 850056   // 
 850057   // Nothing was found; good!
 850058   // 
 850059   return (1);   // true
 850060 }

94.5.11   kernel/fs/inode_file_read.c

Si veda la sezione 93.6.10.

 860001 #include <kernel/fs.h>
 860002 #include <errno.h>
 860003 #include <kernel/lib_k.h>
 860004 //----------------------------------------------------------
 860005 ssize_t
 860006 inode_file_read (inode_t * inode, off_t offset,
 860007                  void *buffer, size_t count, int *eof)
 860008 {
 860009   unsigned char *destination = (unsigned char *) buffer;
 860010   unsigned char zone_buffer[SB_MAX_ZONE_SIZE];
 860011   blkcnt_t blkcnt_read;
 860012   off_t off_fzone;      // File zone offset.
 860013   off_t off_buffer;     // Destination buffer offset.
 860014   ssize_t size_read;    // Byte transfer counter.
 860015   zno_t fzone;
 860016   off_t off_end;
 860017   // 
 860018   // The inode pointer must be valid, and
 860019   // the start byte must be positive.
 860020   // 
 860021   if (inode == NULL || offset < 0)
 860022     {
 860023       errset (EINVAL);  // Invalid argument.
 860024       return ((ssize_t) - 1);
 860025     }
 860026   // 
 860027   // Check if the start address is inside the file
 860028   // size. This is not
 860029   // an error, but zero bytes are read and `*eof' is
 860030   // set. Otherwise,
 860031   // `*eof' is reset.
 860032   // 
 860033   if (offset >= inode->size)
 860034     {
 860035       (eof != NULL) ? *eof = 1 : 0;
 860036       return (0);
 860037     }
 860038   else
 860039     {
 860040       (eof != NULL) ? *eof = 0 : 0;
 860041     }
 860042   // 
 860043   // Adjust, if necessary, the size of read, because
 860044   // it cannot be
 860045   // larger than the actual file size. The variable
 860046   // `off_end' is
 860047   // used to calculate the position *after* the
 860048   // requested read.
 860049   // Remember that the first file position is byte
 860050   // zero; so,
 860051   // the byte index inside the file goes from zero to
 860052   // inode->size -1.
 860053   // 
 860054   off_end = offset;
 860055   off_end += count;
 860056   if (off_end > inode->size)
 860057     {
 860058       count = (inode->size - offset);
 860059     }
 860060   // 
 860061   // Read the first file-zone inside the zone buffer.
 860062   // 
 860063   fzone = offset / inode->sb->blksize;
 860064   off_fzone = offset % inode->sb->blksize;
 860065   blkcnt_read =
 860066     inode_fzones_read (inode, fzone, zone_buffer,
 860067                        (blkcnt_t) 1);
 860068   if (blkcnt_read <= 0)
 860069     {
 860070       // 
 860071       // Sorry!
 860072       // 
 860073 
 860074       k_printf
 860075         ("inode_fzones_read (inode, fzone %i,... )\n",
 860076          fzone);
 860077 
 860078       errset (EUNKNOWN);
 860079       return (0);       // Zero bytes read!
 860080     }
 860081   // 
 860082   // The first file-zone was read: copy it inside the
 860083   // destination
 860084   // buffer and continue reading the other zones
 860085   // needed. Variables
 860086   // `off_buffer' (destination buffer index) and
 860087   // `size_read' (copy
 860088   // byte counter) must be reset here. Variable
 860089   // `off_fzone' is already
 860090   // set with the initial offset inside `zone_buffer'.
 860091   // 
 860092   off_buffer = 0;
 860093   size_read = 0;
 860094   // 
 860095   while (count)
 860096     {
 860097       // 
 860098       // Copy the zone buffer into the destination.
 860099       // Variables
 860100       // `off_fzone', `off_buffer' and `size_read'
 860101       // must not be
 860102       // initialized inside the loop.
 860103       // 
 860104       for (;
 860105            off_fzone < inode->sb->blksize && count > 0;
 860106            off_fzone++, off_buffer++, size_read++,
 860107            count--, offset++)
 860108         {
 860109           destination[off_buffer] = zone_buffer[off_fzone];
 860110         }
 860111       // 
 860112       // If not all the bytes are copied, read the
 860113       // next file-zone.
 860114       // 
 860115       if (count)
 860116         {
 860117           // 
 860118           // Read another file-zone inside the zone
 860119           // buffer.
 860120           // Again, the function `inode_fzones_read()' 
 860121           // might
 860122           // return a null pointer, but the variable
 860123           // `errno' tells if
 860124           // it is really an error. For this reason,
 860125           // the variable
 860126           // `errno' must be reset before the read,
 860127           // and checked after
 860128           // it.
 860129           // 
 860130           fzone = offset / inode->sb->blksize;
 860131           off_fzone = offset % inode->sb->blksize;
 860132           blkcnt_read =
 860133             inode_fzones_read (inode, fzone,
 860134                                zone_buffer, (blkcnt_t) 1);
 860135           if (blkcnt_read <= 0)
 860136             {
 860137               // 
 860138               // Sorry: only `size_read' bytes read!
 860139               // 
 860140               errset (EUNKNOWN);
 860141               return (size_read);
 860142             }
 860143         }
 860144     }
 860145   // 
 860146   // The requested size was read completely.
 860147   // 
 860148   return (size_read);
 860149 }

94.5.12   kernel/fs/inode_file_write.c

Si veda la sezione 93.6.11.

 870001 #include <kernel/fs.h>
 870002 #include <errno.h>
 870003 #include <kernel/lib_k.h>
 870004 //----------------------------------------------------------
 870005 ssize_t
 870006 inode_file_write (inode_t * inode, off_t offset,
 870007                   const void *buffer, size_t count)
 870008 {
 870009   unsigned char *buffer_source = (unsigned char *) buffer;
 870010   unsigned char buffer_zone[SB_MAX_ZONE_SIZE];
 870011   off_t off_fzone;      // File zone offset.
 870012   off_t off_source;     // Source buffer offset.
 870013   ssize_t size_copied;  // Byte transfer counter.
 870014   ssize_t size_written; // Byte written counter.
 870015   zno_t fzone;
 870016   zno_t zone;
 870017   blkcnt_t blkcnt_read;
 870018   int status;
 870019   // 
 870020   // The inode pointer must be valid, and
 870021   // the start byte must be positive.
 870022   // 
 870023   if (inode == NULL || offset < 0)
 870024     {
 870025       errset (EINVAL);  // Invalid argument.
 870026       return ((ssize_t) - 1);
 870027     }
 870028   // 
 870029   // Read a zone, modify it with the source buffer,
 870030   // then write it back
 870031   // and continue reading and writing other zones if
 870032   // needed.
 870033   // 
 870034   for (size_written = 0, off_source = 0, size_copied =
 870035        0; count > 0; size_written += size_copied)
 870036     {
 870037       // 
 870038       // Read the next file-zone inside the zone
 870039       // buffer: the function
 870040       // `inode_zone()' is used to create
 870041       // automatically the zone, if
 870042       // it does not exist.
 870043       // 
 870044       fzone = offset / inode->sb->blksize;
 870045       off_fzone = offset % inode->sb->blksize;
 870046       zone = inode_zone (inode, fzone, 1);
 870047       if (zone == 0)
 870048         {
 870049           // 
 870050           // Return previously written bytes. The
 870051           // variable `errno' is
 870052           // already set by `inode_zone()'.
 870053           // 
 870054           return (size_written);
 870055         }
 870056       blkcnt_read =
 870057         inode_fzones_read (inode, fzone, buffer_zone,
 870058                            (blkcnt_t) 1);
 870059       if (blkcnt_read <= 0)
 870060         {
 870061           // 
 870062           // Even if the value is zero, there is a
 870063           // problem reading the
 870064           // zone to be overwritten (because
 870065           // `inode_zone()' should
 870066           // have already created such zone). The
 870067           // variable `errno' is
 870068           // already set by `inode_fzones_read()'.
 870069           // 
 870070           return ((ssize_t) - 1);
 870071         }
 870072       // 
 870073       // The zone was successfully loaded inside the
 870074       // buffer: overwrite
 870075       // the zone buffer with the source buffer.
 870076       // 
 870077       for (size_copied = 0;
 870078            off_fzone < inode->sb->blksize && count > 0;
 870079            off_fzone++, off_source++, size_copied++,
 870080            count--, offset++)
 870081         {
 870082           buffer_zone[off_fzone] =
 870083             buffer_source[off_source];
 870084         }
 870085       // 
 870086       // Save the zone.
 870087       // 
 870088       status = zone_write (inode->sb, zone, buffer_zone);
 870089       if (status != 0)
 870090         {
 870091           // 
 870092           // Cannot save the zone: return the size
 870093           // already written.
 870094           // The variable `errno' is already set by
 870095           // `zone_write()'.
 870096           // 
 870097           return (size_written);
 870098         }
 870099       // 
 870100       // Zone saved: update the file size if necessary 
 870101       // (and the inode
 870102       // too).
 870103       // 
 870104       if (inode->size <= offset)
 870105         {
 870106           inode->size = offset;
 870107           inode->changed = 1;
 870108           inode_save (inode);
 870109         }
 870110     }
 870111   // 
 870112   // All done successfully: return the value.
 870113   // 
 870114   return (size_written);
 870115 }

94.5.13   kernel/fs/inode_free.c

Si veda la sezione 93.6.12.

 880001 #include <kernel/fs.h>
 880002 #include <errno.h>
 880003 #include <kernel/lib_k.h>
 880004 //----------------------------------------------------------
 880005 int
 880006 inode_free (inode_t * inode)
 880007 {
 880008   int map_element;
 880009   int map_bit;
 880010   int map_mask;
 880011   // 
 880012   if (inode == NULL)
 880013     {
 880014       errset (EINVAL);  // Invalid argument.
 880015       return (-1);
 880016     }
 880017   // 
 880018   map_element = inode->ino / 16;
 880019   map_bit = inode->ino % 16;
 880020   map_mask = 1 << map_bit;
 880021   // 
 880022   if (inode->sb->map_inode[map_element] & map_mask)
 880023     {
 880024       inode->sb->map_inode[map_element] -= map_mask;
 880025       inode->sb->changed = 1;
 880026     }
 880027   // 
 880028   inode->mode = 0;
 880029   inode->uid = 0;
 880030   inode->gid = 0;
 880031   inode->size = 0;
 880032   inode->time = 0;
 880033   inode->links = 0;
 880034   inode->changed = 1;
 880035   inode->references = 0;
 880036   // 
 880037   return (inode_save (inode));
 880038 }

94.5.14   kernel/fs/inode_fzones_read.c

Si veda la sezione 93.6.13.

 890001 #include <kernel/fs.h>
 890002 #include <errno.h>
 890003 #include <kernel/lib_k.h>
 890004 //----------------------------------------------------------
 890005 blkcnt_t
 890006 inode_fzones_read (inode_t * inode, zno_t zone_start,
 890007                    void *buffer, blkcnt_t blkcnt)
 890008 {
 890009   unsigned char *destination = (unsigned char *) buffer;
 890010   int status;   // `zone_read()' return value.
 890011   blkcnt_t blkcnt_read; // Zone counter/index.
 890012   zno_t zone;
 890013   zno_t fzone;
 890014   // 
 890015   // Read the zones into the destination buffer.
 890016   // 
 890017   for (blkcnt_read = 0, fzone = zone_start;
 890018        blkcnt_read < blkcnt; blkcnt_read++, fzone++)
 890019     {
 890020       // 
 890021       // Calculate the zone number, from the
 890022       // file-zone, reading the
 890023       // inode. If a zone is not really allocated, the 
 890024       // result is zero
 890025       // and is valid.
 890026       // 
 890027       zone = inode_zone (inode, fzone, 0);
 890028       if (zone == ((zno_t) - 1))
 890029         {
 890030           // 
 890031           // This is an error. Return the read zones
 890032           // quantity.
 890033           // 
 890034           errset (EUNKNOWN);
 890035           return (blkcnt_read);
 890036         }
 890037       // 
 890038       // Update the destination buffer pointer.
 890039       // 
 890040       destination += (blkcnt_read * inode->sb->blksize);
 890041       // 
 890042       // Read the zone inside the destination buffer,
 890043       // but if the zone
 890044       // is zero, a zeroed zone must be filled.
 890045       // 
 890046       if (zone == 0)
 890047         {
 890048           memset (destination, 0,
 890049                   (size_t) inode->sb->blksize);
 890050         }
 890051       else
 890052         {
 890053           status = zone_read (inode->sb, zone, destination);
 890054           if (status != 0)
 890055             {
 890056               // 
 890057               // Could not read the requested zone:
 890058               // return the zones
 890059               // read correctly.
 890060               // 
 890061               errset (EIO);     // I/O error.
 890062               return (blkcnt_read);
 890063             }
 890064         }
 890065     }
 890066   // 
 890067   // All zones read correctly inside the buffer.
 890068   // 
 890069   return (blkcnt_read);
 890070 }

94.5.15   kernel/fs/inode_fzones_write.c

Si veda la sezione 93.6.13.

 900001 #include <kernel/fs.h>
 900002 #include <errno.h>
 900003 #include <kernel/lib_k.h>
 900004 //----------------------------------------------------------
 900005 blkcnt_t
 900006 inode_fzones_write (inode_t * inode, zno_t zone_start,
 900007                     void *buffer, blkcnt_t blkcnt)
 900008 {
 900009   unsigned char *source = (unsigned char *) buffer;
 900010   int status;   // `zone_read()' return value.
 900011   blkcnt_t blkcnt_written;      // Written zones
 900012   // counter.
 900013   zno_t zone;
 900014   zno_t fzone;
 900015   // 
 900016   // Write the zones into the destination buffer.
 900017   // 
 900018   for (blkcnt_written = 0, fzone = zone_start;
 900019        blkcnt_written < blkcnt; blkcnt_written++, fzone++)
 900020     {
 900021       // 
 900022       // Find real zone from file-zone.
 900023       // 
 900024       zone = inode_zone (inode, fzone, 1);
 900025       if (zone == 0 || zone == ((zno_t) - 1))
 900026         {
 900027           // 
 900028           // Function `inode_zone()' should allocate
 900029           // automatically
 900030           // a missing zone and should return a valid
 900031           // zone or
 900032           // (zno_t) -1. Anyway, even if a zero zone
 900033           // is returned,
 900034           // it is an error. Return the
 900035           // `blkcnt_written' value.
 900036           // 
 900037           return (blkcnt_written);
 900038         }
 900039       // 
 900040       // Update the source buffer pointer for the next 
 900041       // zone write.
 900042       // 
 900043       source += (blkcnt_written * inode->sb->blksize);
 900044       // 
 900045       // Write the zone from the buffer content.
 900046       // 
 900047       status = zone_write (inode->sb, zone, source);
 900048       if (status != 0)
 900049         {
 900050           // 
 900051           // Cannot write the zone. Return
 900052           // `size_written_zone' value.
 900053           // 
 900054           return (blkcnt_written);
 900055         }
 900056     }
 900057   // 
 900058   // All zones read correctly inside the buffer.
 900059   // 
 900060   return (blkcnt_written);
 900061 }

94.5.16   kernel/fs/inode_get.c

Si veda la sezione 93.6.15.

 910001 #include <kernel/fs.h>
 910002 #include <errno.h>
 910003 #include <kernel/lib_k.h>
 910004 #include <kernel/dev.h>
 910005 //----------------------------------------------------------
 910006 inode_t *
 910007 inode_get (dev_t device, ino_t ino)
 910008 {
 910009   sb_t *sb;
 910010   inode_t *inode;
 910011   unsigned long int start;
 910012   size_t size;
 910013   ssize_t n;
 910014   int status;
 910015   // 
 910016   // Verify if the root file system inode was
 910017   // requested.
 910018   // 
 910019   if (device == 0 && ino == 1)
 910020     {
 910021       // 
 910022       // Get root file system inode.
 910023       // 
 910024       inode = inode_reference (device, ino);
 910025       if (inode == NULL)
 910026         {
 910027           // 
 910028           // The file system root directory inode is
 910029           // not yet loaded:
 910030           // get the first super block.
 910031           // 
 910032           sb = sb_reference ((dev_t) 0);
 910033           if (sb == NULL || sb->device == 0)
 910034             {
 910035               // 
 910036               // This error should never happen.
 910037               // 
 910038               errset (EUNKNOWN);        // Unknown
 910039               // error.
 910040               return (NULL);
 910041             }
 910042           // 
 910043           // Load the file system root directory inode 
 910044           // (recursive
 910045           // call).
 910046           // 
 910047           inode = inode_get (sb->device, (ino_t) 1);
 910048           if (inode == NULL)
 910049             {
 910050               // 
 910051               // This error should never happen.
 910052               // 
 910053               errset (EUNKNOWN);        // Unknown
 910054               // error.
 910055               return (NULL);
 910056             }
 910057           // 
 910058           // Return the directory inode.
 910059           // 
 910060           return (inode);
 910061         }
 910062       else
 910063         {
 910064           // 
 910065           // The file system root directory inode is
 910066           // already
 910067           // available.
 910068           // 
 910069           if (inode->references >= INODE_MAX_REFERENCES)
 910070             {
 910071               errset (ENFILE);  // Too many files open 
 910072               // in system.
 910073               return (NULL);
 910074             }
 910075           else
 910076             {
 910077               inode->references++;
 910078               return (inode);
 910079             }
 910080         }
 910081     }
 910082   // 
 910083   // A common device-inode pair was requested: try to
 910084   // find an already
 910085   // cached inode.
 910086   // 
 910087   inode = inode_reference (device, ino);
 910088   if (inode != NULL)
 910089     {
 910090       if (inode->references >= INODE_MAX_REFERENCES)
 910091         {
 910092           errset (ENFILE);      // Too many files open 
 910093           // in system.
 910094           return (NULL);
 910095         }
 910096       else
 910097         {
 910098           inode->references++;
 910099           return (inode);
 910100         }
 910101     }
 910102   // 
 910103   // The inode is not yet available: get super block.
 910104   // 
 910105   sb = sb_reference (device);
 910106   if (sb == NULL)
 910107     {
 910108       errset (ENODEV);  // No such device.
 910109       return (NULL);
 910110     }
 910111   // 
 910112   // The super block is available, but the inode is
 910113   // not yet cached.
 910114   // Verify if the inode map reports it as allocated.
 910115   // 
 910116   status = sb_inode_status (sb, ino);
 910117   if (!status)
 910118     {
 910119       // 
 910120       // The inode is not allocated and cannot be
 910121       // loaded.
 910122       // 
 910123       errset (ENOENT);  // No such file or directory.
 910124       return (NULL);
 910125     }
 910126   // 
 910127   // The inode was not already cached, but is
 910128   // considered as allocated
 910129   // inside the inode map. Find a free slot to load
 910130   // the inode inside
 910131   // the inode table (in memory).
 910132   // 
 910133   inode = inode_reference ((dev_t) - 1, (ino_t) - 1);
 910134   if (inode == NULL)
 910135     {
 910136       errset (ENFILE);  // Too many files open in
 910137       // system.
 910138       return (NULL);
 910139     }
 910140   // 
 910141   // A free inode slot was found. The inode must be
 910142   // loaded.
 910143   // Calculate the memory inode size, to be saved
 910144   // inside the file
 910145   // system: the administrative inode data, as it is
 910146   // saved inside
 910147   // the file system. The `inode_t' type is bigger
 910148   // than the real
 910149   // inode administrative size, because it contains
 910150   // more data, that is
 910151   // not saved on disk.
 910152   // 
 910153   size = offsetof (inode_t, sb);
 910154   // 
 910155   // Calculating start position for read.
 910156   // 
 910157   // [1] Boot block.
 910158   // [2] Super block.
 910159   // [3] Inode bit map.
 910160   // [4] Zone bit map.
 910161   // [5] Previous inodes: consider that the inode zero 
 910162   // is
 910163   // present in the inode map, but not in the inode
 910164   // table.
 910165   // 
 910166   start = 1024; // [1]
 910167   start += 1024;        // [2]
 910168   start += (sb->map_inode_blocks * 1024);       // [3]
 910169   start += (sb->map_zone_blocks * 1024);        // [4]
 910170   start += ((ino - 1) * size);  // [5]
 910171   // 
 910172   // Read inode from disk.
 910173   // 
 910174   n =
 910175     dev_io ((pid_t) - 1, device, DEV_READ, start,
 910176             inode, size, NULL);
 910177   if (n != size)
 910178     {
 910179       errset (EIO);     // I/O error.
 910180       return (NULL);
 910181     }
 910182   // 
 910183   // The inode was read: add some data to the working
 910184   // copy in memory.
 910185   // 
 910186   inode->sb = sb;
 910187   inode->sb_attached = NULL;
 910188   inode->ino = ino;
 910189   inode->references = 1;
 910190   inode->changed = 0;
 910191   // 
 910192   inode->blkcnt = inode->size;
 910193   inode->blkcnt /= sb->blksize;
 910194   if (inode->size % sb->blksize)
 910195     {
 910196       inode->blkcnt++;
 910197     }
 910198   // 
 910199   inode->pipe_dir = 1;  // Pipes must start with
 910200   // write.
 910201   inode->pipe_off_read = 0;
 910202   inode->pipe_off_write = 0;
 910203   inode->pipe_ref_read = 0;
 910204   inode->pipe_ref_write = 0;
 910205   // 
 910206   // Return the inode pointer.
 910207   // 
 910208   return (inode);
 910209 }

94.5.17   kernel/fs/inode_pipe_make.c

Si veda la sezione 93.6.16.

 920001 #include <kernel/fs.h>
 920002 #include <sys/stat.h>
 920003 #include <errno.h>
 920004 #include <kernel/lib_k.h>
 920005 #include <kernel/lib_s.h>
 920006 //----------------------------------------------------------
 920007 inode_t *
 920008 inode_pipe_make (void)
 920009 {
 920010   inode_t *inode;
 920011   // 
 920012   // Find a free inode.
 920013   // 
 920014   inode = inode_reference ((dev_t) - 1, (ino_t) - 1);
 920015   if (inode == NULL)
 920016     {
 920017       // 
 920018       // No free slot available.
 920019       // 
 920020       errset (ENFILE);  // Too many files open in
 920021       // system.
 920022       return (NULL);
 920023     }
 920024   // 
 920025   // Put data inside the inode. Please note that
 920026   // `inode->ino' must be
 920027   // zero, because it is necessary to recognize it as
 920028   // an internal
 920029   // inode with no file system. Otherwise, with a
 920030   // value different than
 920031   // zero, `inode_put()' will try to remove it. [*]
 920032   // 
 920033   inode->mode = S_IFIFO;
 920034   inode->uid = 0;
 920035   inode->gid = 0;
 920036   inode->size = 0;
 920037   inode->time = 0;
 920038   inode->links = 0;
 920039   inode->direct[0] = 0;
 920040   inode->direct[1] = 0;
 920041   inode->direct[2] = 0;
 920042   inode->direct[3] = 0;
 920043   inode->direct[4] = 0;
 920044   inode->direct[5] = 0;
 920045   inode->direct[6] = 0;
 920046   inode->indirect1 = 0;
 920047   inode->indirect2 = 0;
 920048   inode->sb_attached = NULL;
 920049   inode->sb = 0;
 920050   inode->ino = 0;       // Must be zero. [*]
 920051   inode->blkcnt = 0;
 920052   inode->references = 1;
 920053   inode->changed = 0;
 920054   inode->pipe_dir = 1;  // Must start with write.
 920055   inode->pipe_off_read = 0;
 920056   inode->pipe_off_write = 0;
 920057   inode->pipe_ref_read = 0;
 920058   inode->pipe_ref_write = 0;
 920059   // 
 920060   // Add all access permissions.
 920061   // 
 920062   inode->mode |= (S_IRWXU | S_IRWXG | S_IRWXO);
 920063   // 
 920064   // Return the inode pointer.
 920065   // 
 920066   return (inode);
 920067 }

94.5.18   kernel/fs/inode_pipe_read.c

Si veda la sezione 93.6.17.

 930001 #include <kernel/fs.h>
 930002 #include <errno.h>
 930003 //----------------------------------------------------------
 930004 ssize_t
 930005 inode_pipe_read (inode_t * inode, void *buffer,
 930006                  size_t count, int *eof)
 930007 {
 930008   unsigned char *buffer_s;
 930009   unsigned char *buffer_d = buffer;
 930010   int i;
 930011   // 
 930012   // The inode pointer must be valid.
 930013   // 
 930014   if (inode == NULL)
 930015     {
 930016       errset (EINVAL);  // Invalid argument.
 930017       return ((ssize_t) - 1);
 930018     }
 930019   // 
 930020   // Check the current pipe direction and see if can
 930021   // be
 930022   // read something.
 930023   // 
 930024   if (inode->pipe_dir)
 930025     {
 930026       // 
 930027       // Write: if indexes are the same, cannot read
 930028       // anything.
 930029       // 
 930030       if (inode->pipe_off_write == inode->pipe_off_read)
 930031         {
 930032           // 
 930033           // Cannot read.
 930034           // 
 930035           if (inode->pipe_ref_write == 0)
 930036             {
 930037               if (eof != NULL)
 930038                 {
 930039                   *eof = 1;
 930040                 }
 930041             }
 930042           return ((ssize_t) 0);
 930043         }
 930044     }
 930045   else
 930046     {
 930047       // 
 930048       // Read: the pipe is waiting for a read.
 930049       // 
 930050       ;
 930051     }
 930052   // 
 930053   // Might read something. Set the pointer to the
 930054   // source buffer,
 930055   // that is the area used for direct zones, including 
 930056   // first
 930057   // indirect pointers (total: (7+2)*2 = 18 bytes).
 930058   // 
 930059   buffer_s = (void *) &(inode->direct[0]);
 930060   // 
 930061   i = 0;
 930062   // 
 930063   if (inode->pipe_off_read >= inode->pipe_off_write)
 930064     {
 930065       for (; i < count; i++)
 930066         {
 930067           if (inode->pipe_off_read < INODE_PIPE_BUFFER_SIZE)
 930068             {
 930069               buffer_d[i] = buffer_s[inode->pipe_off_read];
 930070               inode->pipe_off_read++;
 930071             }
 930072           else
 930073             {
 930074               inode->pipe_off_read = 0;
 930075               break;
 930076             }
 930077         }
 930078     }
 930079   // 
 930080   if (inode->pipe_off_read < inode->pipe_off_write)
 930081     {
 930082       for (; i < count; i++)
 930083         {
 930084           if (inode->pipe_off_read < inode->pipe_off_write)
 930085             {
 930086               buffer_d[i] = buffer_s[inode->pipe_off_read];
 930087               inode->pipe_off_read++;
 930088             }
 930089           else
 930090             {
 930091               break;
 930092             }
 930093         }
 930094     }
 930095   // 
 930096   // At this point, it is time to set the direction to 
 930097   // write;
 930098   // it doesn't matter if the direction is already set 
 930099   // so.
 930100   // 
 930101   if (inode->pipe_off_read == inode->pipe_off_write)
 930102     {
 930103       inode->pipe_dir = 1;
 930104     }
 930105   // 
 930106   // Ok.
 930107   // 
 930108   return ((ssize_t) i);
 930109 }

94.5.19   kernel/fs/inode_pipe_write.c

Si veda la sezione 93.6.18.

 940001 #include <kernel/fs.h>
 940002 #include <errno.h>
 940003 //----------------------------------------------------------
 940004 ssize_t
 940005 inode_pipe_write (inode_t * inode, const void *buffer,
 940006                   size_t count)
 940007 {
 940008   const unsigned char *buffer_s = buffer;
 940009   unsigned char *buffer_d;
 940010   int i;
 940011   // 
 940012   // The inode pointer must be valid.
 940013   // 
 940014   if (inode == NULL)
 940015     {
 940016       errset (EINVAL);  // Invalid argument.
 940017       return ((ssize_t) - 1);
 940018     }
 940019   // 
 940020   // Check the current pipe direction and see if can
 940021   // be
 940022   // written something.
 940023   // 
 940024   if (inode->pipe_dir)
 940025     {
 940026       // 
 940027       // Write: the pipe is waiting for a write.
 940028       // 
 940029       ;
 940030     }
 940031   else
 940032     {
 940033       // 
 940034       // Read: if indexes are the same, cannot write
 940035       // anything.
 940036       // 
 940037       if (inode->pipe_off_write == inode->pipe_off_read)
 940038         {
 940039           // 
 940040           // Cannot write. More checks will be made by 
 940041           // `s_write()'.
 940042           // 
 940043           return ((ssize_t) 0);
 940044         }
 940045     }
 940046   // 
 940047   // Might write something. Set the pointer to the
 940048   // destination buffer,
 940049   // that is the area used for direct zones, including 
 940050   // first indirect
 940051   // pointers (total: (7+2)*2 = 18 bytes).
 940052   // 
 940053   buffer_d = (void *) &(inode->direct[0]);
 940054   // 
 940055   i = 0;
 940056   // 
 940057   if (inode->pipe_off_write >= inode->pipe_off_read)
 940058     {
 940059       for (; i < count; i++)
 940060         {
 940061           if (inode->pipe_off_write <
 940062               INODE_PIPE_BUFFER_SIZE)
 940063             {
 940064               buffer_d[inode->pipe_off_write] = buffer_s[i];
 940065               inode->pipe_off_write++;
 940066             }
 940067           else
 940068             {
 940069               inode->pipe_off_write = 0;
 940070               break;
 940071             }
 940072         }
 940073     }
 940074   // 
 940075   if (inode->pipe_off_write < inode->pipe_off_read)
 940076     {
 940077       for (; i < count; i++)
 940078         {
 940079           if (inode->pipe_off_write < inode->pipe_off_read)
 940080             {
 940081               buffer_d[inode->pipe_off_write] = buffer_s[i];
 940082               inode->pipe_off_write++;
 940083             }
 940084           else
 940085             {
 940086               break;
 940087             }
 940088         }
 940089     }
 940090   // 
 940091   // At this point, it is time to set the direction to 
 940092   // read;
 940093   // it doesn't matter if the direction is already set 
 940094   // so.
 940095   // 
 940096   if (inode->pipe_off_write == inode->pipe_off_read)
 940097     {
 940098       inode->pipe_dir = 0;
 940099     }
 940100   // 
 940101   // Ok.
 940102   // 
 940103   return ((ssize_t) i);
 940104 }

94.5.20   kernel/fs/inode_print.c

Si veda la sezione 93.6.19.

 950001 #include <sys/os32.h>
 950002 #include <kernel/fs.h>
 950003 #include <kernel/lib_k.h>
 950004 #include <time.h>
 950005 //----------------------------------------------------------
 950006 void
 950007 inode_print (void)
 950008 {
 950009   int i;
 950010   dev_t device_attached = 0;
 950011   time_t time;
 950012   struct tm *timeptr;
 950013   char type;
 950014   dev_t device;
 950015   // 
 950016   k_printf
 950017     (" dev   ino ref c mntd t mode  uid gid size Kib "
 950018      "date       time     lnk dirct[0]\n");
 950019   // 
 950020   for (i = 0; i < INODE_MAX_SLOTS; i++)
 950021     {
 950022       if (inode_table[i].references <= 0)
 950023         {
 950024           continue;
 950025         }
 950026       // 
 950027       // Calculate modification time.
 950028       // 
 950029       time = inode_table[i].time;
 950030       // 
 950031       timeptr = gmtime (&time);
 950032       // 
 950033       // Get type from mode.
 950034       // 
 950035       if (S_ISBLK (inode_table[i].mode))
 950036         type = 'b';
 950037       else if (S_ISCHR (inode_table[i].mode))
 950038         type = 'c';
 950039       else if (S_ISFIFO (inode_table[i].mode))
 950040         type = 'p';
 950041       else if (S_ISREG (inode_table[i].mode))
 950042         type = '-';
 950043       else if (S_ISDIR (inode_table[i].mode))
 950044         type = 'd';
 950045       else if (S_ISLNK (inode_table[i].mode))
 950046         type = 'l';
 950047       else if (S_ISSOCK (inode_table[i].mode))
 950048         type = 's';
 950049       else
 950050         type = '?';
 950051       // 
 950052       // Is it a mount point?
 950053       // 
 950054       if (inode_table[i].sb_attached != NULL)
 950055         {
 950056           device_attached =
 950057             inode_table[i].sb_attached->device;
 950058         }
 950059       // 
 950060       // Is there a super block device?
 950061       // 
 950062       if (inode_table[i].sb == NULL)
 950063         {
 950064           device = 0;
 950065         }
 950066       else
 950067         {
 950068           device = inode_table[i].sb->device;
 950069         }
 950070       // 
 950071       // Print data.
 950072       // 
 950073       k_printf
 950074         ("%04x %5i %3i %c %04x %c %04o %4i %3i %8i "
 950075          "%4i.%02i.%02i %2i:%02i:%02i %3i %08x\n",
 950076          (unsigned int) device,
 950077          (unsigned int) inode_table[i].ino,
 950078          (unsigned int) inode_table[i].references,
 950079          (inode_table[i].changed ? '!' : ' '),
 950080          (unsigned int) device_attached, type,
 950081          (unsigned int) inode_table[i].mode,
 950082          (unsigned int) inode_table[i].uid,
 950083          (unsigned int) inode_table[i].gid,
 950084          (unsigned int) (inode_table[i].size / 1024),
 950085          timeptr->tm_year, timeptr->tm_mon,
 950086          timeptr->tm_mday, timeptr->tm_hour,
 950087          timeptr->tm_min, timeptr->tm_sec,
 950088          (unsigned int) inode_table[i].links,
 950089          (unsigned int) inode_table[i].direct[0]);
 950090     }
 950091 }

94.5.21   kernel/fs/inode_put.c

Si veda la sezione 93.6.20.

 960001 #include <kernel/fs.h>
 960002 #include <errno.h>
 960003 #include <kernel/lib_k.h>
 960004 //----------------------------------------------------------
 960005 int
 960006 inode_put (inode_t * inode)
 960007 {
 960008   int status;
 960009   // 
 960010   // Check for valid argument.
 960011   // 
 960012   if (inode == NULL)
 960013     {
 960014       errset (EINVAL);  // Invalid argument.
 960015       return (-1);
 960016     }
 960017   // 
 960018   // Check for valid references.
 960019   // 
 960020   if (inode->references <= 0)
 960021     {
 960022       errset (EUNKNOWN);        // Cannot put an inode with
 960023       return (-1);      // zero or negative
 960024       // references.
 960025     }
 960026   // 
 960027   // Debug.
 960028   // 
 960029   if (inode->ino != 0 && inode->sb->device == 0)
 960030     {
 960031       k_printf
 960032         ("kernel alert: trying to close "
 960033          "inode with device "
 960034          "zero, but a number different than zero!\n");
 960035       errset (EUNKNOWN);        // Cannot put an inode 
 960036       // with
 960037       return (-1);      // zero or negative
 960038       // references.
 960039     }
 960040   // 
 960041   // There is at least one reference: now the
 960042   // references value is
 960043   // reduced.
 960044   // 
 960045   inode->references--;
 960046   inode->changed = 1;
 960047   // 
 960048   // If `inode->ino' is zero, it means that the inode
 960049   // was created in memory, but there is no file system
 960050   // for it. For example, it might be a standard I/O
 960051   // inode create automatically for a process.
 960052   // Inodes with number zero cannot be removed from a
 960053   // file system.
 960054   // 
 960055   if (inode->ino == 0)
 960056     {
 960057       // 
 960058       // Nothing to do: just return.
 960059       // 
 960060       return (0);
 960061     }
 960062   // 
 960063   // References counter might be zero.
 960064   // 
 960065   if (inode->references == 0)
 960066     {
 960067       // 
 960068       // Check if the inode is to be deleted (until
 960069       // there are
 960070       // run time references, the inode cannot be
 960071       // removed).
 960072       // 
 960073       if (inode->links == 0
 960074           || (S_ISDIR (inode->mode) && inode->links == 1))
 960075         {
 960076           // 
 960077           // The inode has no more run time references 
 960078           // and file system
 960079           // links are also zero (or one for a
 960080           // directory): remove it!
 960081           // 
 960082           status = inode_truncate (inode);
 960083           if (status != 0)
 960084             {
 960085               k_perror (NULL);
 960086             }
 960087           // 
 960088           inode_free (inode);
 960089           return (0);
 960090         }
 960091     }
 960092   // 
 960093   // Save inode to disk and return.
 960094   // 
 960095   return (inode_save (inode));
 960096 }

94.5.22   kernel/fs/inode_reference.c

Si veda la sezione 93.6.21.

 970001 #include <kernel/fs.h>
 970002 #include <errno.h>
 970003 //----------------------------------------------------------
 970004 inode_t *
 970005 inode_reference (dev_t device, ino_t ino)
 970006 {
 970007   int s;        // Slot index.
 970008   sb_t *sb_table = sb_reference (0);
 970009   // 
 970010   // If device is zero, and inode is zero, a reference 
 970011   // to the whole
 970012   // table is returned.
 970013   // 
 970014   if (device == 0 && ino == 0)
 970015     {
 970016       return (inode_table);
 970017     }
 970018   // 
 970019   // If device is ((dev_t) -1) and the inode is
 970020   // ((ino_t) -1), a
 970021   // reference to a free inode slot is returned.
 970022   // 
 970023   if (device == (dev_t) - 1 && ino == ((ino_t) - 1))
 970024     {
 970025       for (s = 0; s < INODE_MAX_SLOTS; s++)
 970026         {
 970027           if (inode_table[s].references == 0)
 970028             {
 970029               return (&inode_table[s]);
 970030             }
 970031         }
 970032       return (NULL);
 970033     }
 970034   // 
 970035   // If device is zero and the inode is 1, a reference 
 970036   // to the root
 970037   // directory inode is returned.
 970038   // 
 970039   if (device == 0 && ino == 1)
 970040     {
 970041       // 
 970042       // The super block table is to be scanned.
 970043       // 
 970044       for (device = 0, s = 0; s < SB_MAX_SLOTS; s++)
 970045         {
 970046           if (sb_table[s].device != 0
 970047               && (sb_table[s].inode_mounted_on->
 970048                   sb_attached->device ==
 970049                   sb_table[s].device))
 970050             {
 970051               device = sb_table[s].device;
 970052               break;
 970053             }
 970054         }
 970055       if (device == 0)
 970056         {
 970057           errset (E_CANNOT_FIND_ROOT_DEVICE);
 970058           return (NULL);
 970059         }
 970060       // 
 970061       // Scan the inode table to find inode 1 and the
 970062       // same device.
 970063       // 
 970064       for (s = 0; s < INODE_MAX_SLOTS; s++)
 970065         {
 970066           if (inode_table[s].sb->device == device &&
 970067               inode_table[s].ino == 1)
 970068             {
 970069               return (&inode_table[s]);
 970070             }
 970071         }
 970072       // 
 970073       // Cannot find a root file system inode.
 970074       // 
 970075       errset (E_CANNOT_FIND_ROOT_INODE);
 970076       return (NULL);
 970077     }
 970078   // 
 970079   // A device and an inode number were selected: find
 970080   // the inode
 970081   // associated to it.
 970082   // 
 970083   for (s = 0; s < INODE_MAX_SLOTS; s++)
 970084     {
 970085       if (inode_table[s].sb->device == device &&
 970086           inode_table[s].ino == ino)
 970087         {
 970088           return (&inode_table[s]);
 970089         }
 970090     }
 970091   // 
 970092   // The inode was not found.
 970093   // 
 970094   return (NULL);
 970095 }

94.5.23   kernel/fs/inode_save.c

Si veda la sezione 93.6.22.

 980001 #include <kernel/fs.h>
 980002 #include <errno.h>
 980003 #include <kernel/dev.h>
 980004 //----------------------------------------------------------
 980005 int
 980006 inode_save (inode_t * inode)
 980007 {
 980008   size_t size;
 980009   unsigned long int start;
 980010   ssize_t n;
 980011   // 
 980012   // Check for valid argument.
 980013   // 
 980014   if (inode == NULL)
 980015     {
 980016       errset (EINVAL);  // Invalid argument.
 980017       return (-1);
 980018     }
 980019   // 
 980020   // If the inode number is zero, no file system is
 980021   // involved!
 980022   // 
 980023   if (inode->ino == 0)
 980024     {
 980025       return (0);
 980026     }
 980027   // 
 980028   // Save the super block to disk.
 980029   // 
 980030   sb_save (inode->sb);
 980031   // 
 980032   // Save the inode to disk.
 980033   // 
 980034   if (inode->changed)
 980035     {
 980036       size = offsetof (inode_t, sb);
 980037       // 
 980038       // Calculating start position for write.
 980039       // 
 980040       // 
 980041       // Boot block: 1024 bytes
 980042       // 
 980043       start = 1024;
 980044       // 
 980045       // Super block: + 1024 bytes
 980046       // 
 980047       start += 1024;
 980048       // 
 980049       // Inode bit map:
 980050       // 
 980051       start += (inode->sb->map_inode_blocks * 1024);
 980052       // 
 980053       // Zone bit map:
 980054       // 
 980055       start += (inode->sb->map_zone_blocks * 1024);
 980056       // 
 980057       // Previous inodes: consider that the inode zero
 980058       // is present in the inode map, but not in the
 980059       // inode table.
 980060       // 
 980061       start += ((inode->ino - 1) * size);
 980062       // 
 980063       // Write the inode.
 980064       // 
 980065       n =
 980066         dev_io ((pid_t) - 1, inode->sb->device,
 980067                 DEV_WRITE, start, inode, size, NULL);
 980068       // 
 980069       inode->changed = 0;
 980070     }
 980071   return (0);
 980072 }

94.5.24   kernel/fs/inode_stdio_dev_make.c

Si veda la sezione 93.6.23.

 990001 #include <kernel/fs.h>
 990002 #include <errno.h>
 990003 #include <kernel/lib_k.h>
 990004 #include <kernel/lib_s.h>
 990005 //----------------------------------------------------------
 990006 inode_t *
 990007 inode_stdio_dev_make (dev_t device, mode_t mode)
 990008 {
 990009   inode_t *inode;
 990010   // 
 990011   // Check for arguments.
 990012   // 
 990013   if (mode == 0 || device == 0)
 990014     {
 990015       errset (EINVAL);  // Invalid argument.
 990016       return (NULL);
 990017     }
 990018   // 
 990019   // Find a free inode.
 990020   // 
 990021   inode = inode_reference ((dev_t) - 1, (ino_t) - 1);
 990022   if (inode == NULL)
 990023     {
 990024       // 
 990025       // No free slot available.
 990026       // 
 990027       errset (ENFILE);  // Too many files open in
 990028       // system.
 990029       return (NULL);
 990030     }
 990031   // 
 990032   // Put data inside the inode. Please note that
 990033   // `inode->ino' must be
 990034   // zero, because it is necessary to recognize it as
 990035   // an internal
 990036   // inode with no file system. Otherwise, with a
 990037   // value different than
 990038   // zero, `inode_put()' will try to remove it. [*]
 990039   // 
 990040   inode->mode = mode;
 990041   inode->uid = 0;
 990042   inode->gid = 0;
 990043   inode->size = 0;
 990044   inode->time = s_time ((pid_t) 0, NULL);
 990045   inode->links = 0;
 990046   inode->direct[0] = device;
 990047   inode->direct[1] = 0;
 990048   inode->direct[2] = 0;
 990049   inode->direct[3] = 0;
 990050   inode->direct[4] = 0;
 990051   inode->direct[5] = 0;
 990052   inode->direct[6] = 0;
 990053   inode->indirect1 = 0;
 990054   inode->indirect2 = 0;
 990055   inode->sb_attached = NULL;
 990056   inode->sb = 0;
 990057   inode->ino = 0;       // Must be zero. [*]
 990058   inode->blkcnt = 0;
 990059   inode->references = 1;
 990060   inode->changed = 0;
 990061   // 
 990062   // Add all access permissions.
 990063   // 
 990064   inode->mode |= (S_IRWXU | S_IRWXG | S_IRWXO);
 990065   // 
 990066   // Return the inode pointer.
 990067   // 
 990068   return (inode);
 990069 }

94.5.25   kernel/fs/inode_truncate.c

Si veda la sezione 93.6.24.

1000001 #include <kernel/fs.h>
1000002 #include <errno.h>
1000003 #include <kernel/lib_k.h>
1000004 //----------------------------------------------------------
1000005 int
1000006 inode_truncate (inode_t * inode)
1000007 {
1000008   unsigned int indirect_zones;
1000009   zno_t zone_table1[INODE_MAX_INDIRECT_ZONES];
1000010   zno_t zone_table2[INODE_MAX_INDIRECT_ZONES];
1000011   unsigned int i;       // Direct index.
1000012   unsigned int i0;      // Single indirect index.
1000013   unsigned int i1;      // Double indirect first
1000014   // index.
1000015   unsigned int i2;      // Double indirect second
1000016   // index.
1000017   int status;   // `zone_read()' return value.
1000018   // 
1000019   // Check argument.
1000020   // 
1000021   if (inode == NULL)
1000022     {
1000023       errset (EINVAL);
1000024       return (-1);
1000025     }
1000026   // 
1000027   // Calculate how many indirect zone numbers are
1000028   // stored inside
1000029   // a zone: it depends on the zone size.
1000030   // 
1000031   indirect_zones = inode->sb->blksize / 2;
1000032   // 
1000033   // Scan and release direct zones. Errors are
1000034   // ignored.
1000035   // 
1000036   for (i = 0; i < 7; i++)
1000037     {
1000038       zone_free (inode->sb, inode->direct[i]);
1000039       inode->direct[i] = 0;
1000040     }
1000041   // 
1000042   // Scan single indirect zones, if present.
1000043   // 
1000044   if (inode->blkcnt > 7 && inode->indirect1 != 0)
1000045     {
1000046       // 
1000047       // There is a single indirect table to load.
1000048       // Errors are
1000049       // almost ignored.
1000050       // 
1000051       status =
1000052         zone_read (inode->sb, inode->indirect1,
1000053                    zone_table1);
1000054       if (status == 0)
1000055         {
1000056           // 
1000057           // Scan the table and remove zones.
1000058           // 
1000059           for (i0 = 0; i0 < indirect_zones; i0++)
1000060             {
1000061               zone_free (inode->sb, zone_table1[i0]);
1000062             }
1000063         }
1000064       // 
1000065       // Remove indirect table too.
1000066       // 
1000067       zone_free (inode->sb, inode->indirect1);
1000068       // 
1000069       // Clear single indirect reference inside the
1000070       // inode.
1000071       // 
1000072       inode->indirect1 = 0;
1000073     }
1000074   // 
1000075   // Scan double indirect zones, if present.
1000076   // 
1000077   if (inode->blkcnt > (7 + indirect_zones)
1000078       && inode->indirect2 != 0)
1000079     {
1000080       // 
1000081       // There is a double indirect table to load.
1000082       // Errors are
1000083       // almost ignored.
1000084       // 
1000085       status =
1000086         zone_read (inode->sb, inode->indirect2,
1000087                    zone_table1);
1000088       if (status == 0)
1000089         {
1000090           // 
1000091           // Scan the table and get second level
1000092           // indirection.
1000093           // 
1000094           for (i1 = 0; i1 < indirect_zones; i1++)
1000095             {
1000096               if ((inode->blkcnt
1000097                    >
1000098                    (7 + indirect_zones +
1000099                     indirect_zones * i1))
1000100                   && zone_table1[i1] != 0)
1000101                 {
1000102                   // 
1000103                   // There is a second level table to
1000104                   // load.
1000105                   // 
1000106                   status =
1000107                     zone_read (inode->sb,
1000108                                zone_table1[i1],
1000109                                zone_table2);
1000110                   if (status == 0)
1000111                     {
1000112                       // 
1000113                       // Release zones.
1000114                       // 
1000115                       for (i2 = 0;
1000116                            i2 < indirect_zones &&
1000117                            (inode->blkcnt >
1000118                             (7 + indirect_zones +
1000119                              indirect_zones * i1 +
1000120                              i2)); i2++)
1000121                         {
1000122                           zone_free (inode->sb,
1000123                                      zone_table2[i2]);
1000124                         }
1000125                       // 
1000126                       // Remove second level indirect
1000127                       // table.
1000128                       // 
1000129                       zone_free (inode->sb,
1000130                                  zone_table1[i1]);
1000131                     }
1000132                 }
1000133             }
1000134           // 
1000135           // Remove first level indirect table.
1000136           // 
1000137           zone_free (inode->sb, inode->indirect2);
1000138         }
1000139       // 
1000140       // Clear single indirect reference inside the
1000141       // inode.
1000142       // 
1000143       inode->indirect2 = 0;
1000144     }
1000145   // 
1000146   // Update super block and inode data.
1000147   // 
1000148   sb_save (inode->sb);
1000149   inode->size = 0;
1000150   inode->changed = 1;
1000151   inode_save (inode);
1000152   // 
1000153   // Successful return.
1000154   // 
1000155   return (0);
1000156 }

94.5.26   kernel/fs/inode_zone.c

Si veda la sezione 93.6.25.

1010001 #include <kernel/fs.h>
1010002 #include <errno.h>
1010003 #include <kernel/lib_k.h>
1010004 //----------------------------------------------------------
1010005 zno_t
1010006 inode_zone (inode_t * inode, zno_t fzone, int write)
1010007 {
1010008   unsigned int indirect_zones;
1010009   unsigned int allocated_zone;
1010010   zno_t zone_table[INODE_MAX_INDIRECT_ZONES];
1010011   char buffer[SB_MAX_ZONE_SIZE];
1010012   unsigned int i0;      // Single indirect index.  
1010013   unsigned int i1;      // Double indirect first
1010014   // index.
1010015   unsigned int i2;      // Double indirect second
1010016   // index.
1010017   int status;
1010018   zno_t zone_second;    // Second level table zone.
1010019   // 
1010020   // Check to have a valid inode.
1010021   // 
1010022   if (inode == NULL)
1010023     {
1010024       errset (EINVAL);
1010025       return ((zno_t) - 1);
1010026     }
1010027   // 
1010028   // Calculate how many indirect zone numbers are
1010029   // stored inside
1010030   // a zone: it depends on the zone size.
1010031   // 
1010032   indirect_zones = inode->sb->blksize / 2;
1010033   // 
1010034   // Convert file-zone number into a zone number.
1010035   // 
1010036   if (fzone < 7)
1010037     {
1010038       // 
1010039       // 0 <= fzone <= 6
1010040       // The zone number is inside the direct zone
1010041       // references.
1010042       // Verify to have such zone.
1010043       // 
1010044       if (inode->direct[fzone] == 0)
1010045         {
1010046           // 
1010047           // There is not such zone, but we do not
1010048           // consider
1010049           // it an error, because a file can be not
1010050           // contiguous.
1010051           // 
1010052           if (!write)
1010053             {
1010054               return ((zno_t) 0);
1010055             }
1010056           // 
1010057           // Must be allocated.
1010058           // 
1010059           allocated_zone = zone_alloc (inode->sb);
1010060           if (allocated_zone == 0)
1010061             {
1010062               // 
1010063               // Cannot allocate the zone. The
1010064               // variable `errno' is
1010065               // set by `zone_alloc()'.
1010066               // 
1010067               return ((zno_t) - 1);
1010068             }
1010069           // 
1010070           // The zone is allocated: clear the zone and 
1010071           // save.
1010072           // 
1010073           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010074           status =
1010075             zone_write (inode->sb, allocated_zone, buffer);
1010076           if (status < 0)
1010077             {
1010078               // 
1010079               // Cannot overwrite the zone. The
1010080               // variable `errno' is
1010081               // set by `zone_write()'.
1010082               // 
1010083               return ((zno_t) - 1);
1010084             }
1010085           // 
1010086           // The zone is allocated and cleared: save
1010087           // the inode.
1010088           // 
1010089           inode->direct[fzone] = allocated_zone;
1010090           inode->changed = 1;
1010091           status = inode_save (inode);
1010092           if (status != 0)
1010093             {
1010094               // 
1010095               // Cannot save the inode. The variable
1010096               // `errno' is
1010097               // set `inode_save()'.
1010098               // 
1010099               return ((zno_t) - 1);
1010100             }
1010101         }
1010102       // 
1010103       // The zone is there: return it.
1010104       // 
1010105       return (inode->direct[fzone]);
1010106     }
1010107   if (fzone < 7 + indirect_zones)
1010108     {
1010109       // 
1010110       // 7 <= fzone <= (6 + indirect_zones)
1010111       // The zone number is inside the single indirect 
1010112       // zone
1010113       // references: verify to have the indirect zone
1010114       // table.
1010115       // 
1010116       if (inode->indirect1 == 0)
1010117         {
1010118           // 
1010119           // There is not such zone, but it is not an
1010120           // error.
1010121           // 
1010122           if (!write)
1010123             {
1010124               return ((zno_t) 0);
1010125             }
1010126           // 
1010127           // The first level of indirection must be
1010128           // initialized.
1010129           // 
1010130           allocated_zone = zone_alloc (inode->sb);
1010131           if (allocated_zone == 0)
1010132             {
1010133               // 
1010134               // Cannot allocate the zone for the
1010135               // indirection table:
1010136               // this is an error and the `errno'
1010137               // value is produced
1010138               // by `zone_alloc()'.
1010139               // 
1010140               return ((zno_t) - 1);
1010141             }
1010142           // 
1010143           // The zone for the indirection table is
1010144           // allocated:
1010145           // clear the zone and save.
1010146           // 
1010147           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010148           status =
1010149             zone_write (inode->sb, allocated_zone, buffer);
1010150           if (status < 0)
1010151             {
1010152               // 
1010153               // Cannot overwrite the zone. The
1010154               // variable `errno' is
1010155               // set by `zone_write()'.
1010156               // 
1010157               return ((zno_t) - 1);
1010158             }
1010159           // 
1010160           // The indirection table zone is allocated
1010161           // and cleared:
1010162           // save the inode.
1010163           // 
1010164           inode->indirect1 = allocated_zone;
1010165           inode->changed = 1;
1010166           status = inode_save (inode);
1010167           if (status != 0)
1010168             {
1010169               // 
1010170               // Cannot save the inode. This is an
1010171               // error and the value
1010172               // for `errno' is produced by
1010173               // `inode_save()'.
1010174               // 
1010175               return ((zno_t) - 1);
1010176             }
1010177         }
1010178       // 
1010179       // An indirect table is present inside the file
1010180       // system:
1010181       // load it.
1010182       // 
1010183       status =
1010184         zone_read (inode->sb, inode->indirect1, zone_table);
1010185       if (status != 0)
1010186         {
1010187           // 
1010188           // Cannot load the indirect table. This is
1010189           // an error and the
1010190           // value for `errno' is assigned by function 
1010191           // `zone_read()'.
1010192           // 
1010193           return ((zno_t) - 1);
1010194         }
1010195       // 
1010196       // The indirect table was read. Calculate the
1010197       // index inside
1010198       // the table, for the requested zone.
1010199       // 
1010200       i0 = (fzone - 7);
1010201       // 
1010202       // Check if the zone is to be allocated.
1010203       // 
1010204       if (zone_table[i0] == 0)
1010205         {
1010206           // 
1010207           // There is not such zone, but it is not an
1010208           // error.
1010209           // 
1010210           if (!write)
1010211             {
1010212               return ((zno_t) 0);
1010213             }
1010214           // 
1010215           // The zone must be allocated.
1010216           // 
1010217           allocated_zone = zone_alloc (inode->sb);
1010218           if (allocated_zone == 0)
1010219             {
1010220               // 
1010221               // There is no space for the zone
1010222               // allocation. The
1010223               // variable `errno' is already updated
1010224               // by
1010225               // `zone_alloc()'.
1010226               // 
1010227               return ((zno_t) - 1);
1010228             }
1010229           // 
1010230           // The zone is allocated: clear the zone and 
1010231           // save.
1010232           // 
1010233           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010234           status =
1010235             zone_write (inode->sb, allocated_zone, buffer);
1010236           if (status < 0)
1010237             {
1010238               // 
1010239               // Cannot overwrite the zone. The
1010240               // variable `errno' is
1010241               // set by `zone_write()'.
1010242               // 
1010243               return ((zno_t) - 1);
1010244             }
1010245           // 
1010246           // The zone is allocated and cleared: update 
1010247           // the indirect
1010248           // zone table an save it. The inode is not
1010249           // modified,
1010250           // because the indirect table is outside.
1010251           // 
1010252           zone_table[i0] = allocated_zone;
1010253           status =
1010254             zone_write (inode->sb, inode->indirect1,
1010255                         zone_table);
1010256           if (status != 0)
1010257             {
1010258               // 
1010259               // Cannot save the zone. The variable
1010260               // `errno' is already
1010261               // set by `zone_write()'.
1010262               // 
1010263               return ((zno_t) - 1);
1010264             }
1010265         }
1010266       // 
1010267       // The zone is allocated.
1010268       // 
1010269       return (zone_table[i0]);
1010270     }
1010271   else
1010272     {
1010273       // 
1010274       // (7 + indirect_zones) <= fzone
1010275       // The zone number is inside the double indirect 
1010276       // zone
1010277       // references.
1010278       // Verify to have the first level of second
1010279       // indirection.
1010280       // 
1010281       if (inode->indirect2 == 0)
1010282         {
1010283           // 
1010284           // There is not such zone, but it is not an
1010285           // error.
1010286           // 
1010287           if (!write)
1010288             {
1010289               return ((zno_t) 0);
1010290             }
1010291           // 
1010292           // The first level of second indirection
1010293           // must be
1010294           // initialized.
1010295           // 
1010296           allocated_zone = zone_alloc (inode->sb);
1010297           if (allocated_zone == 0)
1010298             {
1010299               // 
1010300               // Cannot allocate the zone. The
1010301               // variable `errno' is
1010302               // set by `zone_alloc()'.
1010303               // 
1010304               return ((zno_t) - 1);
1010305             }
1010306           // 
1010307           // The zone for the indirection table is
1010308           // allocated:
1010309           // clear the zone and save.
1010310           // 
1010311           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010312           status =
1010313             zone_write (inode->sb, allocated_zone, buffer);
1010314           if (status < 0)
1010315             {
1010316               // 
1010317               // Cannot overwrite the zone. The
1010318               // variable `errno' is
1010319               // set by `zone_write()'.
1010320               // 
1010321               return ((zno_t) - 1);
1010322             }
1010323           // 
1010324           // The zone for the indirection table is
1010325           // allocated and
1010326           // cleared: save the inode.
1010327           // 
1010328           inode->indirect2 = allocated_zone;
1010329           inode->changed = 1;
1010330           status = inode_save (inode);
1010331           if (status != 0)
1010332             {
1010333               // 
1010334               // Cannot save the inode. The variable
1010335               // `errno' is
1010336               // set by `inode_save()'.
1010337               // 
1010338               return ((zno_t) - 1);
1010339             }
1010340         }
1010341       // 
1010342       // The first level of second indirection is
1010343       // present:
1010344       // Read the second indirect table.
1010345       // 
1010346       status =
1010347         zone_read (inode->sb, inode->indirect2, zone_table);
1010348       if (status != 0)
1010349         {
1010350           // 
1010351           // Cannot read the second indirect table.
1010352           // The variable
1010353           // `errno' is set by `zone_read()'.
1010354           // 
1010355           return ((zno_t) - 1);
1010356         }
1010357       // 
1010358       // The first double indirect table was read:
1010359       // calculate
1010360       // indexes inside first and second level of
1010361       // table.
1010362       // 
1010363       fzone -= 7;
1010364       fzone -= indirect_zones;
1010365       i1 = fzone / indirect_zones;
1010366       i2 = fzone % indirect_zones;
1010367       // 
1010368       // Verify to have a second level.
1010369       // 
1010370       if (zone_table[i1] == 0)
1010371         {
1010372           // 
1010373           // There is not such zone, but it is not an
1010374           // error.
1010375           // 
1010376           if (!write)
1010377             {
1010378               return ((zno_t) 0);
1010379             }
1010380           // 
1010381           // The second level must be initialized.
1010382           // 
1010383           allocated_zone = zone_alloc (inode->sb);
1010384           if (allocated_zone == 0)
1010385             {
1010386               // 
1010387               // Cannot allocate the zone. The
1010388               // variable `errno' is set
1010389               // by `zone_alloc()'.
1010390               // 
1010391               return ((zno_t) - 1);
1010392             }
1010393           // 
1010394           // The zone for the indirection table is
1010395           // allocated:
1010396           // clear the zone and save.
1010397           // 
1010398           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010399           status =
1010400             zone_write (inode->sb, allocated_zone, buffer);
1010401           if (status < 0)
1010402             {
1010403               // 
1010404               // Cannot overwrite the zone. The
1010405               // variable `errno' is
1010406               // set by `zone_write()'.
1010407               // 
1010408               return ((zno_t) - 1);
1010409             }
1010410           // 
1010411           // Update the first level index and save it.
1010412           // 
1010413           zone_table[i1] = allocated_zone;
1010414           status =
1010415             zone_write (inode->sb, inode->indirect2,
1010416                         zone_table);
1010417           if (status != 0)
1010418             {
1010419               // 
1010420               // Cannot write the zone. The variable
1010421               // `errno' is set
1010422               // by `zone_write()'.
1010423               // 
1010424               return ((zno_t) - 1);
1010425             }
1010426         }
1010427       // 
1010428       // The second level can be read, overwriting the 
1010429       // array
1010430       // `zone_table[]'. The zone number for the
1010431       // second level
1010432       // indirection table is saved inside
1010433       // `zone_second', before
1010434       // overwriting the array.
1010435       // 
1010436       zone_second = zone_table[i1];
1010437       status =
1010438         zone_read (inode->sb, zone_second, zone_table);
1010439       if (status != 0)
1010440         {
1010441           // 
1010442           // Cannot read the second level indirect
1010443           // table. The variable
1010444           // `errno' is set by `zone_read()'.
1010445           // 
1010446           return ((zno_t) - 1);
1010447         }
1010448       // 
1010449       // The second level was read and `zone_table[]'
1010450       // is now
1010451       // such second one: check if the zone is to be
1010452       // allocated.
1010453       // 
1010454       if (zone_table[i2] == 0)
1010455         {
1010456           // 
1010457           // There is not such zone, but it is not an
1010458           // error.
1010459           // 
1010460           if (!write)
1010461             {
1010462               return ((zno_t) 0);
1010463             }
1010464           // 
1010465           // Must be allocated.
1010466           // 
1010467           allocated_zone = zone_alloc (inode->sb);
1010468           if (allocated_zone == 0)
1010469             {
1010470               // 
1010471               // Cannot allocate the zone. The
1010472               // variable `errno' is set
1010473               // by `zone_alloc()'.
1010474               // 
1010475               return ((zno_t) - 1);
1010476             }
1010477           // 
1010478           // The zone is allocated: clear the zone and 
1010479           // save.
1010480           // 
1010481           memset (buffer, 0, SB_MAX_ZONE_SIZE);
1010482           status =
1010483             zone_write (inode->sb, allocated_zone, buffer);
1010484           if (status < 0)
1010485             {
1010486               // 
1010487               // Cannot overwrite the zone. The
1010488               // variable `errno' is
1010489               // set by `zone_write()'.
1010490               // 
1010491               return ((zno_t) - 1);
1010492             }
1010493           // 
1010494           // The zone was allocated and cleared:
1010495           // update the indirect
1010496           // zone table an save it. The inode is not
1010497           // modified, because
1010498           // the indirect table is outside.
1010499           // 
1010500           zone_table[i2] = allocated_zone;
1010501           status =
1010502             zone_write (inode->sb, zone_second, zone_table);
1010503           if (status != 0)
1010504             {
1010505               // 
1010506               // Cannot write the zone. The variable
1010507               // `errno' is set
1010508               // by `zone_write()'.
1010509               // 
1010510               return ((zno_t) - 1);
1010511             }
1010512         }
1010513       // 
1010514       // The zone is there: return the zone number.
1010515       // 
1010516       return (zone_table[i2]);
1010517     }
1010518 }

94.5.27   kernel/fs/path_device.c

Si veda la sezione 93.6.38.

1020001 #include <kernel/fs.h>
1020002 #include <errno.h>
1020003 #include <kernel/proc.h>
1020004 //----------------------------------------------------------
1020005 dev_t
1020006 path_device (pid_t pid, const char *path)
1020007 {
1020008   proc_t *ps;
1020009   inode_t *inode;
1020010   dev_t device;
1020011   // 
1020012   // Get process.
1020013   // 
1020014   ps = proc_reference (pid);
1020015   // 
1020016   inode = path_inode (pid, path);
1020017   if (inode == NULL)
1020018     {
1020019       errset (errno);
1020020       return ((dev_t) - 1);
1020021     }
1020022   // 
1020023   if (!(S_ISBLK (inode->mode) || S_ISCHR (inode->mode)))
1020024     {
1020025       errset (ENODEV);  // No such device.
1020026       inode_put (inode);
1020027       return ((dev_t) - 1);
1020028     }
1020029   // 
1020030   device = inode->direct[0];
1020031   inode_put (inode);
1020032   return (device);
1020033 }

94.5.28   kernel/fs/path_fix.c

Si veda la sezione 93.6.39.

1030001 #include <kernel/fs.h>
1030002 #include <errno.h>
1030003 #include <kernel/proc.h>
1030004 //----------------------------------------------------------
1030005 int
1030006 path_fix (char *path)
1030007 {
1030008   char new_path[PATH_MAX];
1030009   char *token[PATH_MAX / 4];
1030010   int t;        // Token index.
1030011   int token_size;       // Token array effective size.
1030012   int comp;     // String compare return value.
1030013   size_t path_size;     // Path string size.
1030014   // 
1030015   // Initialize token search.
1030016   // 
1030017   token[0] = strtok (path, "/");
1030018   // 
1030019   // Scan tokens.
1030020   // 
1030021   for (t = 0;
1030022        t < PATH_MAX / 4 && token[t] != NULL;
1030023        t++, token[t] = strtok (NULL, "/"))
1030024     {
1030025       // 
1030026       // If current token is `.', just ignore it.
1030027       // 
1030028       comp = strcmp (token[t], ".");
1030029       if (comp == 0)
1030030         {
1030031           t--;
1030032         }
1030033       // 
1030034       // If current token is `..', remove previous
1030035       // token,
1030036       // if there is one.
1030037       // 
1030038       comp = strcmp (token[t], "..");
1030039       if (comp == 0)
1030040         {
1030041           if (t > 0)
1030042             {
1030043               t -= 2;
1030044             }
1030045           else
1030046             {
1030047               t = -1;
1030048             }
1030049         }
1030050       // 
1030051       // `t' will be incremented and another token
1030052       // will be
1030053       // found.
1030054       // 
1030055     }
1030056   // 
1030057   // Save the token array effective size.
1030058   // 
1030059   token_size = t;
1030060   // 
1030061   // Initialize the new path string.
1030062   // 
1030063   new_path[0] = '\0';
1030064   // 
1030065   // Build the new path string.
1030066   // 
1030067   if (token_size > 0)
1030068     {
1030069       for (t = 0; t < token_size; t++)
1030070         {
1030071           path_size = strlen (new_path);
1030072           strncat (new_path, "/", 2);
1030073           strncat (new_path, token[t],
1030074                    PATH_MAX - path_size - 1);
1030075         }
1030076     }
1030077   else
1030078     {
1030079       strncat (new_path, "/", 2);
1030080     }
1030081   // 
1030082   // Copy the new path into the original string.
1030083   // 
1030084   strncpy (path, new_path, PATH_MAX);
1030085   // 
1030086   // Return.
1030087   // 
1030088   return (0);
1030089 }

94.5.29   kernel/fs/path_full.c

Si veda la sezione 93.6.40.

1040001 #include <kernel/fs.h>
1040002 #include <errno.h>
1040003 #include <kernel/proc.h>
1040004 //----------------------------------------------------------
1040005 int
1040006 path_full (const char *path, const char *path_cwd,
1040007            char *full_path)
1040008 {
1040009   unsigned int path_size;
1040010   // 
1040011   // Check some arguments.
1040012   // 
1040013   if (path == NULL || strlen (path) == 0
1040014       || full_path == NULL)
1040015     {
1040016       errset (EINVAL);  // Invalid argument.
1040017       return (-1);
1040018     }
1040019   // 
1040020   // The main path and the receiving one are right.
1040021   // Now arrange to get a full path name.
1040022   // 
1040023   if (path[0] == '/')
1040024     {
1040025       strncpy (full_path, path, PATH_MAX);
1040026       full_path[PATH_MAX - 1] = 0;
1040027     }
1040028   else
1040029     {
1040030       if (path_cwd == NULL || strlen (path_cwd) == 0)
1040031         {
1040032           errset (EINVAL);      // Invalid argument.
1040033           return (-1);
1040034         }
1040035       strncpy (full_path, path_cwd, PATH_MAX);
1040036       path_size = strlen (full_path);
1040037       strncat (full_path, "/", (PATH_MAX - path_size));
1040038       path_size = strlen (full_path);
1040039       strncat (full_path, path, (PATH_MAX - path_size));
1040040     }
1040041   // 
1040042   // Fix path name so that it has no `..', `.', and no
1040043   // multiple `/'.
1040044   // 
1040045   path_fix (full_path);
1040046   // 
1040047   // Return.
1040048   // 
1040049   return (0);
1040050 }

94.5.30   kernel/fs/path_inode.c

Si veda la sezione 93.6.41.

1050001 #include <kernel/fs.h>
1050002 #include <errno.h>
1050003 #include <kernel/proc.h>
1050004 #include <kernel/lib_k.h>
1050005 //----------------------------------------------------------
1050006 #define DIRECTORY_BUFFER_SIZE (SB_MAX_ZONE_SIZE/16)
1050007 //----------------------------------------------------------
1050008 inode_t *
1050009 path_inode (pid_t pid, const char *path)
1050010 {
1050011   proc_t *ps;
1050012   inode_t *inode;
1050013   dev_t device;
1050014   char full_path[PATH_MAX];
1050015   char *name;
1050016   char *next;
1050017   directory_t dir[DIRECTORY_BUFFER_SIZE];
1050018   char dir_name[NAME_MAX + 1];
1050019   off_t offset_dir;
1050020   ssize_t size_read;
1050021   size_t dir_size_read;
1050022   ssize_t size_to_read;
1050023   int comp;
1050024   int d;        // Directory index;
1050025   int status;   // inode_check() return status.
1050026   // 
1050027   // Get process.
1050028   // 
1050029   ps = proc_reference (pid);
1050030   // 
1050031   // Arrange to get a packed full path name.
1050032   // 
1050033   path_full (path, ps->path_cwd, full_path);
1050034   // 
1050035   // Get the root file system inode.
1050036   // 
1050037   inode = inode_get ((dev_t) 0, 1);
1050038   if (inode == NULL)
1050039     {
1050040       errset (errno);
1050041       return (NULL);
1050042     }
1050043   // 
1050044   // Save the device number.
1050045   // 
1050046   device = inode->sb->device;
1050047   // 
1050048   // Variable `inode' already points to the root file
1050049   // system inode:
1050050   // It must be a directory!
1050051   // 
1050052   status =
1050053     inode_check (inode, S_IFDIR, 1, ps->euid, ps->egid);
1050054   if (status != 0)
1050055     {
1050056       // 
1050057       // Variable `errno' should be set by
1050058       // inode_check().
1050059       // 
1050060       errset (errno);
1050061       inode_put (inode);
1050062       return (NULL);
1050063     }
1050064   // 
1050065   // Initialize string scan: find the first path
1050066   // token, after the
1050067   // first `/'.
1050068   // 
1050069   name = strtok (full_path, "/");
1050070   // 
1050071   // If the original full path is just `/' the
1050072   // variable `name'
1050073   // appears as a null pointer, and the variable
1050074   // `inode' is already
1050075   // what we are looking for.
1050076   // 
1050077   if (name == NULL)
1050078     {
1050079       return (inode);
1050080     }
1050081   // 
1050082   // There is at least a name after `/' inside the
1050083   // original full
1050084   // path. A scan is going to start: the original
1050085   // value for variable
1050086   // `inode' is a pointer to the root directory inode.
1050087   // 
1050088   for (;;)
1050089     {
1050090       // 
1050091       // Find next token.
1050092       // 
1050093       next = strtok (NULL, "/");
1050094       // 
1050095       // Read the directory from the current inode.
1050096       // 
1050097       for (offset_dir = 0;; offset_dir += size_read)
1050098         {
1050099           size_to_read = DIRECTORY_BUFFER_SIZE;
1050100           // 
1050101           if ((offset_dir + size_to_read) > inode->size)
1050102             {
1050103               size_to_read = inode->size - offset_dir;
1050104             }
1050105           // 
1050106           size_read =
1050107             inode_file_read (inode, offset_dir, dir,
1050108                              size_to_read, NULL);
1050109           // 
1050110           // The size read must be a multiple of 16.
1050111           // 
1050112           size_read = ((size_read / 16) * 16);
1050113           // 
1050114           // Check anyway if it is zero.
1050115           // 
1050116           if (size_read == 0)
1050117             {
1050118               // 
1050119               // The directory is ended: release the
1050120               // inode and return.
1050121               // 
1050122               inode_put (inode);
1050123               errset (ENOENT);  // No such file or
1050124               // directory.
1050125               return (NULL);
1050126             }
1050127           // 
1050128           // Calculate how many directory items we
1050129           // have read.
1050130           // 
1050131           dir_size_read = size_read / 16;
1050132           // 
1050133           // Scan the directory to find the current
1050134           // name.
1050135           // 
1050136           for (d = 0; d < dir_size_read; d++)
1050137             {
1050138               // 
1050139               // Ensure to have a null terminated
1050140               // string for
1050141               // the name found.
1050142               // 
1050143               memcpy (dir_name, dir[d].name,
1050144                       (size_t) NAME_MAX);
1050145               dir_name[NAME_MAX] = 0;
1050146               // 
1050147               comp = strcmp (name, dir_name);
1050148               if (comp == 0 && dir[d].ino != 0)
1050149                 {
1050150                   // 
1050151                   // Found the name and verified that
1050152                   // it has a link to
1050153                   // a inode. Now release the
1050154                   // directory inode.
1050155                   // 
1050156                   inode_put (inode);
1050157                   // 
1050158                   // Get next inode and break the
1050159                   // loop.
1050160                   // 
1050161                   inode = inode_get (device, dir[d].ino);
1050162                   break;
1050163                 }
1050164             }
1050165           // 
1050166           // If index `d' is in a valid range, the
1050167           // name was found.
1050168           // 
1050169           if (d < dir_size_read)
1050170             {
1050171               // 
1050172               // The name was found.
1050173               // 
1050174               break;
1050175             }
1050176         }
1050177       // 
1050178       // If the function is still working, a file or a 
1050179       // directory
1050180       // was found: see if there is another name after 
1050181       // this one
1050182       // to look for. If there isn't, just break the
1050183       // loop.
1050184       // 
1050185       if (next == NULL)
1050186         {
1050187           // 
1050188           // As no other tokens are to be found, break 
1050189           // the loop.
1050190           // 
1050191           break;
1050192         }
1050193       // 
1050194       // As there is another name after the current
1050195       // one,
1050196       // the current file must be a directory.
1050197       // 
1050198       status =
1050199         inode_check (inode, S_IFDIR, 1, ps->euid, ps->egid);
1050200       if (status != 0)
1050201         {
1050202           // 
1050203           // Variable `errno' is set by
1050204           // `inode_check()'.
1050205           // 
1050206           errset (errno);
1050207           inode_put (inode);
1050208           return (NULL);
1050209         }
1050210       // 
1050211       // The inode is a directory and the user has the 
1050212       // necessary
1050213       // permissions: check if it is a mount point and 
1050214       // go to the
1050215       // new device root directory if necessary.
1050216       // 
1050217       if (inode->sb_attached != NULL)
1050218         {
1050219           // 
1050220           // Must find the root directory for the new
1050221           // device, and
1050222           // then go to that inode.
1050223           // 
1050224           device = inode->sb_attached->device;
1050225           inode_put (inode);
1050226           inode = inode_get (device, 1);
1050227           status = inode_check (inode, S_IFDIR, 1,
1050228                                 ps->euid, ps->egid);
1050229           if (status != 0)
1050230             {
1050231               inode_put (inode);
1050232               return (NULL);
1050233             }
1050234         }
1050235       // 
1050236       // As a directory was found, and another token
1050237       // follows it,
1050238       // must continue the token scan.
1050239       // 
1050240       name = next;
1050241     }
1050242   // 
1050243   // Current inode found is the file represented by
1050244   // the requested
1050245   // path.
1050246   // 
1050247   return (inode);
1050248 }

94.5.31   kernel/fs/path_inode_link.c

Si veda la sezione 93.6.42.

1060001 #include <kernel/fs.h>
1060002 #include <errno.h>
1060003 #include <kernel/proc.h>
1060004 #include <libgen.h>
1060005 //----------------------------------------------------------
1060006 inode_t *
1060007 path_inode_link (pid_t pid, const char *path,
1060008                  inode_t * inode, mode_t mode)
1060009 {
1060010   proc_t *ps;
1060011   char buffer[SB_MAX_ZONE_SIZE];
1060012   off_t start;
1060013   int d;        // Directory index.
1060014   ssize_t size_read;
1060015   ssize_t size_written;
1060016   directory_t *dir = (directory_t *) buffer;
1060017   char path_copy1[PATH_MAX];
1060018   char path_copy2[PATH_MAX];
1060019   char *path_directory;
1060020   char *path_name;
1060021   inode_t *inode_directory;
1060022   inode_t *inode_new;
1060023   dev_t device;
1060024   int status;
1060025   // 
1060026   // Check arguments.
1060027   // 
1060028   if (path == NULL || strlen (path) == 0)
1060029     {
1060030       errset (EINVAL);  // Invalid argument:
1060031       return (NULL);    // the path is mandatory.
1060032     }
1060033   // 
1060034   if (inode == NULL && mode == 0)
1060035     {
1060036       errset (EINVAL);  // Invalid argument: if the
1060037       // inode is to
1060038       return (NULL);    // be created, the mode is
1060039       // mandatory.
1060040     }
1060041   // 
1060042   if (inode != NULL)
1060043     {
1060044       if (mode != 0)
1060045         {
1060046           errset (EINVAL);      // Invalid argument:
1060047           // if the inode is
1060048           return (NULL);        // already present,
1060049           // the creation mode
1060050         }       // must not be given.
1060051       if (S_ISDIR (inode->mode))
1060052         {
1060053           errset (EPERM);       // Operation not
1060054           // permitted.
1060055           return (NULL);        // Refuse to link
1060056           // directory.
1060057         }
1060058       if (inode->links >= LINK_MAX)
1060059         {
1060060           errset (EMLINK);      // Too many links.
1060061           return (NULL);
1060062         }
1060063     }
1060064   // 
1060065   // Get process.
1060066   // 
1060067   ps = proc_reference (pid);
1060068   // 
1060069   // If the destination path already exists, the link
1060070   // cannot be made.
1060071   // It does not matter if the inode is known or not.
1060072   // 
1060073   inode_new = path_inode ((uid_t) 0, path);
1060074   if (inode_new != NULL)
1060075     {
1060076       // 
1060077       // A file already exists with the same name.
1060078       // 
1060079       inode_put (inode_new);
1060080       errset (EEXIST);  // File exists.
1060081       return (NULL);
1060082     }
1060083   // 
1060084   // At this point, `inode_new' is `NULL'.
1060085   // Copy the source path inside the directory path
1060086   // and name arrays.
1060087   // 
1060088   strncpy (path_copy1, path, PATH_MAX);
1060089   strncpy (path_copy2, path, PATH_MAX);
1060090   // 
1060091   // Reduce to directory name and find the last name.
1060092   // 
1060093   path_directory = dirname (path_copy1);
1060094   path_name = basename (path_copy2);
1060095   if (strlen (path_directory) == 0
1060096       || strlen (path_name) == 0)
1060097     {
1060098       errset (EACCES);  // Permission denied: maybe
1060099       // the
1060100       // original path is the root directory
1060101       // and cannot find a previous directory.
1060102       return (NULL);
1060103     }
1060104   // 
1060105   // Get the directory inode.
1060106   // 
1060107   inode_directory = path_inode (pid, path_directory);
1060108   if (inode_directory == NULL)
1060109     {
1060110       errset (errno);
1060111       return (NULL);
1060112     }
1060113   // 
1060114   // Check if something is mounted on it.
1060115   // 
1060116   if (inode_directory->sb_attached != NULL)
1060117     {
1060118       // 
1060119       // Must select the right directory.
1060120       // 
1060121       device = inode_directory->sb_attached->device;
1060122       inode_put (inode_directory);
1060123       inode_directory = inode_get (device, 1);
1060124       if (inode_directory == NULL)
1060125         {
1060126           return (NULL);
1060127         }
1060128     }
1060129   // 
1060130   // If the inode to link is known, check if the
1060131   // selected directory
1060132   // has the same super block than the inode to link.
1060133   // 
1060134   if (inode != NULL && inode_directory->sb != inode->sb)
1060135     {
1060136       inode_put (inode_directory);
1060137       errset (ENOENT);  // No such file or directory.
1060138       return (NULL);
1060139     }
1060140   // 
1060141   // Check if write is allowed for the file system.
1060142   // 
1060143   if (inode_directory->sb->options & MOUNT_RO)
1060144     {
1060145       inode_put (inode_directory);
1060146       errset (EROFS);   // Read-only file system.
1060147       return (NULL);
1060148     }
1060149   // 
1060150   // Verify access permissions for the directory. The
1060151   // number "3" means
1060152   // that the user must have access permission and
1060153   // write permission:
1060154   // "-wx" == 2+1 == 3.
1060155   // 
1060156   status = inode_check (inode_directory, S_IFDIR, 3,
1060157                         ps->euid, ps->egid);
1060158   if (status != 0)
1060159     {
1060160       inode_put (inode_directory);
1060161       return (NULL);
1060162     }
1060163   // 
1060164   // If the inode to link was not specified, it must
1060165   // be created.
1060166   // From now on, the inode is referenced with the
1060167   // variable
1060168   // `inode_new'.
1060169   // 
1060170   inode_new = inode;
1060171   // 
1060172   if (inode_new == NULL)
1060173     {
1060174       inode_new =
1060175         inode_alloc (inode_directory->sb->device, mode,
1060176                      ps->euid, ps->egid);
1060177       if (inode_new == NULL)
1060178         {
1060179           // 
1060180           // The inode allocation failed, so, also the 
1060181           // directory
1060182           // must be released, before return.
1060183           // 
1060184           inode_put (inode_directory);
1060185           return (NULL);
1060186         }
1060187     }
1060188   // 
1060189   // Read the directory content and try to add the new 
1060190   // item.
1060191   // 
1060192   for (start = 0;
1060193        start < inode_directory->size;
1060194        start += inode_directory->sb->blksize)
1060195     {
1060196       size_read =
1060197         inode_file_read (inode_directory, start,
1060198                          buffer,
1060199                          inode_directory->sb->blksize,
1060200                          NULL);
1060201       if (size_read < sizeof (directory_t))
1060202         {
1060203           break;
1060204         }
1060205       // 
1060206       // Scan the directory portion just read, for an
1060207       // unused item.
1060208       // 
1060209       dir = (directory_t *) buffer;
1060210       for (d = 0; d < size_read;
1060211            d += (sizeof (directory_t)), dir++)
1060212         {
1060213           if (dir->ino == 0)
1060214             {
1060215               // 
1060216               // Found an empty directory item: link
1060217               // the inode.
1060218               // 
1060219               dir->ino = inode_new->ino;
1060220               strncpy (dir->name, path_name, NAME_MAX);
1060221               inode_new->links++;
1060222               inode_new->changed = 1;
1060223               // 
1060224               // Update the directory inside the file
1060225               // system.
1060226               // 
1060227               size_written =
1060228                 inode_file_write (inode_directory,
1060229                                   start, buffer, size_read);
1060230               if (size_written != size_read)
1060231                 {
1060232                   // 
1060233                   // Write problem: release the
1060234                   // directory and return.
1060235                   // 
1060236                   inode_put (inode_directory);
1060237                   errset (EUNKNOWN);
1060238                   return (NULL);
1060239                 }
1060240               // 
1060241               // Save the new inode, release the
1060242               // directory and return
1060243               // the linked inode.
1060244               // 
1060245               inode_save (inode_new);
1060246               inode_put (inode_directory);
1060247               return (inode_new);
1060248             }
1060249         }
1060250     }
1060251   // 
1060252   // The directory don't have a free item and one must 
1060253   // be appended.
1060254   // 
1060255   dir = (directory_t *) buffer;
1060256   start = inode_directory->size;
1060257   // 
1060258   // Prepare the buffer with the link.
1060259   // 
1060260   dir->ino = inode_new->ino;
1060261   strncpy (dir->name, path_name, NAME_MAX);
1060262   inode_new->links++;
1060263   inode_new->changed = 1;
1060264   // 
1060265   // Append the buffer to the directory.
1060266   // 
1060267   size_written =
1060268     inode_file_write (inode_directory, start, buffer,
1060269                       (sizeof (directory_t)));
1060270   if (size_written != (sizeof (directory_t)))
1060271     {
1060272       // 
1060273       // Problem updating the directory: release it
1060274       // and return.
1060275       // 
1060276       inode_put (inode_directory);
1060277       errset (EUNKNOWN);
1060278       return (NULL);
1060279     }
1060280   // 
1060281   // Close access to the directory inode and save the
1060282   // other inode,
1060283   // with updated link count.
1060284   // 
1060285   inode_put (inode_directory);
1060286   inode_save (inode_new);
1060287   // 
1060288   // Return successfully.
1060289   // 
1060290   return (inode_new);
1060291 }

94.5.32   kernel/fs/sb_inode_status.c

Si veda la sezione 93.6.26.

1070001 #include <kernel/fs.h>
1070002 #include <errno.h>
1070003 //----------------------------------------------------------
1070004 int
1070005 sb_inode_status (sb_t * sb, ino_t ino)
1070006 {
1070007   int map_element;
1070008   int map_bit;
1070009   int map_mask;
1070010   // 
1070011   // Check arguments.
1070012   // 
1070013   if (ino == 0 || sb == NULL)
1070014     {
1070015       errset (EINVAL);  // Invalid argument.
1070016       return (-1);
1070017     }
1070018   // 
1070019   // Calculate the map element, the map bit and the
1070020   // map mask.
1070021   // 
1070022   map_element = ino / 16;
1070023   map_bit = ino % 16;
1070024   map_mask = 1 << map_bit;
1070025   // 
1070026   // Check the inode and return.
1070027   // 
1070028   if (sb->map_inode[map_element] & map_mask)
1070029     {
1070030       return (1);       // True.
1070031     }
1070032   else
1070033     {
1070034       return (0);       // False.
1070035     }
1070036 }

94.5.33   kernel/fs/sb_mount.c

Si veda la sezione 93.6.27.

1080001 #include <kernel/fs.h>
1080002 #include <errno.h>
1080003 #include <kernel/dev.h>
1080004 #include <kernel/lib_k.h>
1080005 #include <kernel/dm.h>
1080006 #include <kernel/part.h>
1080007 //----------------------------------------------------------
1080008 sb_t *
1080009 sb_mount (dev_t device, inode_t ** inode_mnt, int options)
1080010 {
1080011   sb_t *sb;
1080012   ssize_t size_read;
1080013   addr_t start;
1080014   int m;
1080015   size_t size_sb;
1080016   size_t size_map;
1080017   int dev_major = major (device);
1080018   int dev_minor = minor (device);
1080019   int p = dev_minor & 0x000F;
1080020   int d = ((dev_minor & 0x00F0) >> 4);
1080021   // 
1080022   // Find if it is already mounted.
1080023   // 
1080024   sb = sb_reference (device);
1080025   if (sb != NULL)
1080026     {
1080027       errset (EBUSY);   // Device or resource busy:
1080028       // device
1080029       return (NULL);    // already mounted.
1080030     }
1080031   // 
1080032   // Find if `*inode_mnt' is already mounting
1080033   // something.
1080034   // 
1080035   if (*inode_mnt != NULL
1080036       && (*inode_mnt)->sb_attached != NULL)
1080037     {
1080038       errset (EBUSY);   // Device or resource busy:
1080039       // mount point
1080040       return (NULL);    // already used.
1080041     }
1080042   // 
1080043   // If it is a partition, find if it can be mounted.
1080044   // 
1080045   if ((dev_major == DEV_DM_MAJOR) && (p));
1080046   {
1080047     // 
1080048     // It is a partition.
1080049     // 
1080050     if (dm_table[d].part[p].type != PART_TYPE_MINIX)
1080051       {
1080052         errset (E_PART_TYPE_NOT_MINIX); // Not Minix!
1080053         return (NULL);  // Cannot mount.
1080054       }
1080055   }
1080056   // 
1080057   // The inode is not yet mounting anything, or it is
1080058   // new: find a free
1080059   // slot inside the super block table.
1080060   // 
1080061   sb = sb_reference ((dev_t) - 1);
1080062   if (sb == NULL)
1080063     {
1080064       errset (EBUSY);   // Device or resource busy:
1080065       return (NULL);    // no free slots.
1080066     }
1080067   // 
1080068   // A free slot was found: the super block header
1080069   // must be loaded, but
1080070   // before it is necessary to calculate the header
1080071   // size to be read.
1080072   // 
1080073   size_sb = offsetof (sb_t, device);
1080074   // 
1080075   // Then fix the starting point.
1080076   // 
1080077   start = 1024; // After boot block.
1080078   // 
1080079   // Read the file system super block header.
1080080   // 
1080081   size_read =
1080082     dev_io ((pid_t) 0, device, DEV_READ, start, sb,
1080083             size_sb, NULL);
1080084   if (size_read != size_sb)
1080085     {
1080086       errset (EIO);     // I/O error.
1080087       return (NULL);
1080088     }
1080089   // 
1080090   // Save some more data.
1080091   // 
1080092   sb->device = device;
1080093   sb->options = options;
1080094   sb->inode_mounted_on = *inode_mnt;
1080095   sb->blksize = (1024 << sb->log2_size_zone);
1080096   // 
1080097   // Check if the super block data is valid.
1080098   // 
1080099   if (sb->magic_number != 0x137F)
1080100     {
1080101       errset (ENODEV);  // No such device: unsupported
1080102       sb->device = 0;   // file system type.
1080103       return (NULL);
1080104     }
1080105   if (sb->map_inode_blocks > SB_MAX_INODE_BLOCKS)
1080106     {
1080107       errset (E_MAP_INODE_TOO_BIG);
1080108       return (NULL);
1080109     }
1080110   if (sb->map_zone_blocks > SB_MAX_ZONE_BLOCKS)
1080111     {
1080112       errset (E_MAP_ZONE_TOO_BIG);
1080113       return (NULL);
1080114     }
1080115   if (sb->blksize > SB_MAX_ZONE_SIZE)
1080116     {
1080117       errset (E_DATA_ZONE_TOO_BIG);
1080118       return (NULL);
1080119     }
1080120   // 
1080121   // A right super block header was loaded from disk,
1080122   // now load the super block inode bit map.
1080123   // 
1080124   start = 1024; // After boot block.
1080125   start += 1024;        // After super block.
1080126   // 
1080127   // Reset map in memory before loading.
1080128   // 
1080129   for (m = 0; m < SB_MAP_INODE_SIZE; m++)       // [2]
1080130     {
1080131       sb->map_inode[m] = 0xFFFF;        // [2]
1080132     }
1080133   size_map = sb->map_inode_blocks * 1024;
1080134   size_read =
1080135     dev_io ((pid_t) - 1, sb->device, DEV_READ, start,
1080136             sb->map_inode, size_map, NULL);
1080137   if (size_read != size_map)
1080138     {
1080139       errset (EIO);     // I/O error.
1080140       return (NULL);
1080141     }
1080142   // 
1080143   // Load the super block zone bit map.
1080144   // 
1080145   // After boot block:
1080146   // 
1080147   start = 1024;
1080148   // 
1080149   // After the super block:
1080150   // 
1080151   start += 1024;
1080152   // 
1080153   // After inode bit map:
1080154   // 
1080155   start += (sb->map_inode_blocks * 1024);
1080156   // 
1080157   // Reset map in memory, before loading.
1080158   // 
1080159   for (m = 0; m < SB_MAP_ZONE_SIZE; m++)
1080160     {
1080161       sb->map_zone[m] = 0xFFFF;
1080162     }
1080163   // 
1080164   size_map = sb->map_zone_blocks * 1024;
1080165   size_read =
1080166     dev_io ((pid_t) - 1, sb->device, DEV_READ, start,
1080167             sb->map_zone, size_map, NULL);
1080168   if (size_read != size_map)
1080169     {
1080170       errset (EIO);     // I/O error.
1080171       return (NULL);
1080172     }
1080173   // 
1080174   // Check the inode that should mount the super
1080175   // block. If `*inode_mnt' is `NULL', then it is meant
1080176   // to be the first mount of the root file system.
1080177   // In such case, the inode must be loaded too,
1080178   // and the value for `*inode_mnt' must be modified.
1080179   // 
1080180   if (*inode_mnt == NULL)
1080181     {
1080182       *inode_mnt = inode_get (device, 1);
1080183     }
1080184   // 
1080185   // Check for a valid value.
1080186   // 
1080187   if (*inode_mnt == NULL)
1080188     {
1080189       // 
1080190       // This is bad!
1080191       // 
1080192       errset (EUNKNOWN);        // Unknown error.
1080193       return (NULL);
1080194     }
1080195   // 
1080196   // A valid inode is available for the mount.
1080197   // 
1080198   (*inode_mnt)->sb_attached = sb;
1080199   // 
1080200   // Update the super block too.
1080201   // 
1080202   sb->inode_mounted_on = *inode_mnt;
1080203   // 
1080204   // Return the super block pointer.
1080205   // 
1080206   return (sb);
1080207 }

94.5.34   kernel/fs/sb_print.c

Si veda la sezione 93.6.28.

1090001 #include <sys/os32.h>
1090002 #include <kernel/fs.h>
1090003 #include <kernel/lib_k.h>
1090004 //----------------------------------------------------------
1090005 void
1090006 sb_print (void)
1090007 {
1090008   int s;
1090009   // 
1090010   k_printf
1090011     ("     mnt                1st zone max file "
1090012      " inode zone  \n");
1090013   k_printf
1090014     ("dev  dev  inodes blocks dz  size size KiB "
1090015      "blocks blocks\n");
1090016   // 
1090017   for (s = 0; s < SB_MAX_SLOTS; s++)
1090018     {
1090019       if (sb_table[s].device == 0)
1090020         {
1090021           continue;
1090022         }
1090023       k_printf
1090024         ("%04x %04x % 6i % 6i % 3i "
1090025          "% 4i % 8i % 6i % 6i\n",
1090026          sb_table[s].device,
1090027          sb_table[s].inode_mounted_on->sb_attached->device,
1090028          sb_table[s].inodes, sb_table[s].zones,
1090029          sb_table[s].first_data_zone,
1090030          (1024 << sb_table[s].log2_size_zone),
1090031          sb_table[s].max_file_size / 1024,
1090032          sb_table[s].map_inode_blocks,
1090033          sb_table[s].map_zone_blocks);
1090034     }
1090035 }

94.5.35   kernel/fs/sb_reference.c

Si veda la sezione 93.6.29.

1100001 #include <kernel/fs.h>
1100002 #include <errno.h>
1100003 //----------------------------------------------------------
1100004 sb_t *
1100005 sb_reference (dev_t device)
1100006 {
1100007   int s;        // Slot index.
1100008   // 
1100009   // If device is zero, a reference to the whole table 
1100010   // is returned.
1100011   // 
1100012   if (device == 0)
1100013     {
1100014       return (sb_table);
1100015     }
1100016   // 
1100017   // If device is ((dev_t) -1), a reference to a free
1100018   // slot is
1100019   // returned.
1100020   // 
1100021   if (device == ((dev_t) - 1))
1100022     {
1100023       for (s = 0; s < SB_MAX_SLOTS; s++)
1100024         {
1100025           if (sb_table[s].device == 0)
1100026             {
1100027               return (&sb_table[s]);
1100028             }
1100029         }
1100030       return (NULL);
1100031     }
1100032   // 
1100033   // A device was selected: find the super block
1100034   // associated to it.
1100035   // 
1100036   for (s = 0; s < SB_MAX_SLOTS; s++)
1100037     {
1100038       if (sb_table[s].device == device)
1100039         {
1100040           return (&sb_table[s]);
1100041         }
1100042     }
1100043   // 
1100044   // The super block was not found.
1100045   // 
1100046   return (NULL);
1100047 }

94.5.36   kernel/fs/sb_save.c

Si veda la sezione 93.6.30.

1110001 #include <kernel/fs.h>
1110002 #include <errno.h>
1110003 #include <kernel/dev.h>
1110004 //----------------------------------------------------------
1110005 int
1110006 sb_save (sb_t * sb)
1110007 {
1110008   ssize_t size_written;
1110009   addr_t start;
1110010   size_t size_map;
1110011   // 
1110012   // Check for valid argument.
1110013   // 
1110014   if (sb == NULL)
1110015     {
1110016       errset (EINVAL);  // Invalid argument.
1110017       return (-1);
1110018     }
1110019   // 
1110020   // Check if the super block changed for some reason
1110021   // (only the inode and the zone maps can change
1110022   // really).
1110023   // 
1110024   if (!sb->changed)
1110025     {
1110026       // 
1110027       // Nothing to save.
1110028       // 
1110029       return (0);
1110030     }
1110031   // 
1110032   // Something inside the super block changed: start
1110033   // the procedure to save the inode map (recall that
1110034   // the super block header is not saved, because it
1110035   // never changes).
1110036   // 
1110037   start = 1024; // After boot block.
1110038   start += 1024;        // After super block.
1110039   size_map = sb->map_inode_blocks * 1024;
1110040   size_written =
1110041     dev_io ((pid_t) - 1, sb->device, DEV_WRITE, start,
1110042             sb->map_inode, size_map, NULL);
1110043   if (size_written != size_map)
1110044     {
1110045       // 
1110046       // Error writing the map.
1110047       // 
1110048       errset (EIO);     // I/O error.
1110049       return (-1);
1110050     }
1110051   // 
1110052   // Start the procedure to save the zone map.
1110053   // 
1110054   start = 1024; // After boot block.
1110055   start += 1024;        // After super block.
1110056   start += (sb->map_inode_blocks * 1024);       // After 
1110057   // inode bit
1110058   // map.
1110059   size_map = sb->map_zone_blocks * 1024;
1110060   size_written =
1110061     dev_io ((pid_t) - 1, sb->device, DEV_WRITE, start,
1110062             sb->map_zone, size_map, NULL);
1110063   if (size_written != size_map)
1110064     {
1110065       // 
1110066       // Error writing the map.
1110067       // 
1110068       errset (EIO);     // I/O error.
1110069       return (-1);
1110070     }
1110071   // 
1110072   // Super block saved.
1110073   // 
1110074   sb->changed = 0;
1110075   // 
1110076   return (0);
1110077 }

94.5.37   kernel/fs/sb_zone_status.c

Si veda la sezione 93.6.26.

1120001 #include <kernel/fs.h>
1120002 #include <errno.h>
1120003 //----------------------------------------------------------
1120004 int
1120005 sb_zone_status (sb_t * sb, zno_t zone)
1120006 {
1120007   int map_element;
1120008   int map_bit;
1120009   int map_mask;
1120010   // 
1120011   // Check arguments.
1120012   // 
1120013   if (zone == 0 || sb == NULL)
1120014     {
1120015       errset (EINVAL);  // Invalid argument.
1120016       return (-1);
1120017     }
1120018   // 
1120019   // Calculate the map element, the map bit and the
1120020   // map mask.
1120021   // 
1120022   map_element = zone / 16;
1120023   map_bit = zone % 16;
1120024   map_mask = 1 << map_bit;
1120025   // 
1120026   // Check the zone and return.
1120027   // 
1120028   if (sb->map_zone[map_element] & map_mask)
1120029     {
1120030       return (1);       // True.
1120031     }
1120032   else
1120033     {
1120034       return (0);       // False.
1120035     }
1120036 }

94.5.38   kernel/fs/sock_free_port.c

Si veda la sezione 93.6.32.

1130001 #include <kernel/fs.h>
1130002 #include <errno.h>
1130003 #include <fcntl.h>
1130004 //----------------------------------------------------------
1130005 h_port_t
1130006 sock_free_port (void)
1130007 {
1130008   int skn;
1130009   h_port_t lport;
1130010   // 
1130011   for (lport = 0xFFFF; lport >= 1024; lport--)
1130012     {
1130013       for (skn = 0; skn < SOCK_MAX_SLOTS; skn++)
1130014         {
1130015           if (sock_table[skn].lport == lport)
1130016             {
1130017               // 
1130018               // The port is used.
1130019               // 
1130020               break;
1130021             }
1130022         }
1130023       if (sock_table[skn].lport != lport)
1130024         {
1130025           // 
1130026           // The port is new.
1130027           // 
1130028           return (lport);
1130029         }
1130030     }
1130031   // 
1130032   // If we are here, no free port was found.
1130033   // 
1130034   return ((h_port_t) 0);
1130035 }

94.5.39   kernel/fs/sock_reference.c

Si veda la sezione 93.6.33.

1140001 #include <kernel/fs.h>
1140002 #include <errno.h>
1140003 #include <fcntl.h>
1140004 //----------------------------------------------------------
1140005 sock_t *
1140006 sock_reference (int skn)
1140007 {
1140008   // 
1140009   // Check type of request.
1140010   // 
1140011   if (skn < 0)
1140012     {
1140013       // 
1140014       // Find a free slot.
1140015       // 
1140016       for (skn = 0; skn < SOCK_MAX_SLOTS; skn++)
1140017         {
1140018           if (sock_table[skn].active == 0)
1140019             {
1140020               return (&sock_table[skn]);
1140021             }
1140022         }
1140023       return (NULL);
1140024     }
1140025   else if (skn > SOCK_MAX_SLOTS)
1140026     {
1140027       return (NULL);
1140028     }
1140029   else
1140030     {
1140031       return (&sock_table[skn]);
1140032     }
1140033 }

94.5.40   kernel/fs/zone_alloc.c

Si veda la sezione 93.6.34.

1150001 #include <kernel/fs.h>
1150002 #include <kernel/dev.h>
1150003 #include <errno.h>
1150004 //----------------------------------------------------------
1150005 zno_t
1150006 zone_alloc (sb_t * sb)
1150007 {
1150008   int m;        // Index inside the inode map.
1150009   int map_element;
1150010   int map_bit;
1150011   int map_mask;
1150012   zno_t zone;
1150013   char buffer[SB_MAX_ZONE_SIZE];
1150014   int status;
1150015   // 
1150016   // Verify if write is allowed.
1150017   // 
1150018   if (sb->options & MOUNT_RO)
1150019     {
1150020       errset (EROFS);   // Read-only file system.
1150021       return ((zno_t) 0);
1150022     }
1150023   // 
1150024   // Write allowed: scan the zone map, to find a free
1150025   // zone. If a free zone can be found, allocate it
1150026   // inside the map.
1150027   // Index `m' starts from one, because the first bit
1150028   // of the map is reserved for a `zero' data-zone
1150029   // that does not exist: the second bit is for the
1150030   // real first data-zone.
1150031   // 
1150032   for (zone = 0, m = 1; m < (SB_MAP_ZONE_SIZE * 16); m++)
1150033     {
1150034       map_element = m / 16;
1150035       map_bit = m % 16;
1150036       map_mask = 1 << map_bit;
1150037       if (!(sb->map_zone[map_element] & map_mask))
1150038         {
1150039           // 
1150040           // Found a free place: set the map.
1150041           // 
1150042           sb->map_zone[map_element] |= map_mask;
1150043           sb->changed = 1;
1150044           // 
1150045           // The *second* bit inside the map is for
1150046           // the first data zone (the zone after the
1150047           // inode table inside the file system),
1150048           // because the first is for a special
1150049           // `zero' data zone, not really used.
1150050           // 
1150051           zone = sb->first_data_zone + m - 1;   // Found 
1150052           // a free
1150053           // zone.
1150054           // 
1150055           // If the zone is outside the disk size, let 
1150056           // set the map bit, but reset variable
1150057           // `zone'.
1150058           // 
1150059           if (zone >= sb->zones)
1150060             {
1150061               zone = 0;
1150062             }
1150063           else
1150064             {
1150065               break;
1150066             }
1150067         }
1150068     }
1150069   if (zone == 0)
1150070     {
1150071       errset (ENOSPC);  // No space left on device.
1150072       return ((zno_t) 0);
1150073     }
1150074   // 
1150075   // A free zone was found and the map was modified
1150076   // inside
1150077   // the super block in memory. The zone must be
1150078   // cleared.
1150079   // 
1150080   status = zone_write (sb, zone, buffer);
1150081   if (status != 0)
1150082     {
1150083       zone_free (sb, zone);
1150084       return ((zno_t) 0);
1150085     }
1150086   // 
1150087   // A zone was allocated: return the number.
1150088   // 
1150089   return (zone);
1150090 }

94.5.41   kernel/fs/zone_free.c

Si veda la sezione 93.6.34.

1160001 #include <kernel/fs.h>
1160002 #include <kernel/dev.h>
1160003 #include <errno.h>
1160004 //----------------------------------------------------------
1160005 int
1160006 zone_free (sb_t * sb, zno_t zone)
1160007 {
1160008   int map_element;
1160009   int map_bit;
1160010   int map_mask;
1160011   // 
1160012   // Check arguments.
1160013   // 
1160014   if (sb == NULL || zone < sb->first_data_zone)
1160015     {
1160016       errset (EINVAL);  // Invalid argument.
1160017       return (-1);
1160018     }
1160019   // 
1160020   // Calculate the map element, the map bit and the
1160021   // map mask.
1160022   // 
1160023   // The *second* bit inside the map is for the first
1160024   // data-zone
1160025   // (the zone after the inode table inside the file
1160026   // system),
1160027   // because the first is for a special `zero'
1160028   // data-zone, not
1160029   // really used.
1160030   // 
1160031   map_element = (zone - sb->first_data_zone + 1) / 16;
1160032   map_bit = (zone - sb->first_data_zone + 1) % 16;
1160033   map_mask = 1 << map_bit;
1160034   // 
1160035   // Verify if the requested zone is inside the file
1160036   // system area.
1160037   // 
1160038   if (zone >= sb->zones)
1160039     {
1160040       errset (EINVAL);  // Invalid argument.
1160041       return (-1);
1160042     }
1160043   // 
1160044   // Free the zone and return.
1160045   // 
1160046   if (sb->map_zone[map_element] & map_mask)
1160047     {
1160048       sb->map_zone[map_element] &= ~map_mask;
1160049       sb->changed = 1;
1160050       return (0);
1160051     }
1160052   else
1160053     {
1160054       errset (EUNKNOWN);        // The zone was
1160055       // already free.
1160056       return (-1);
1160057     }
1160058 }

94.5.42   kernel/fs/zone_print.c

Si veda la sezione 93.6.36.

1170001 #include <sys/os32.h>
1170002 #include <kernel/fs.h>
1170003 #include <kernel/dev.h>
1170004 #include <errno.h>
1170005 //----------------------------------------------------------
1170006 void
1170007 zone_print (sb_t * sb, zno_t zone)
1170008 {
1170009   char buffer[SB_MAX_ZONE_SIZE];
1170010   int status;
1170011   int i;
1170012   int x;
1170013   // 
1170014   status = zone_read (sb, zone, buffer);
1170015   // 
1170016   if (status < 0)
1170017     {
1170018       k_perror (NULL);
1170019       return;
1170020     }
1170021   // 
1170022   // Print.
1170023   // 
1170024   k_printf
1170025     ("dev: 0x%04x, first dzone: %i zone read: %i\n",
1170026      sb->device, sb->first_data_zone, zone);
1170027   // 
1170028   // Will print at most the first 256 byte only!
1170029   // 
1170030   for (i = 0; i < sb->blksize && i < 256; i++)
1170031     {
1170032       k_printf ("%02x ", buffer[i]);
1170033       x = (i + 1) % 4;
1170034       if (x == 0 && i > 0)
1170035         {
1170036           k_printf ("| ");
1170037         }
1170038       x = (i + 1) % 16;
1170039       if (x == 0 && i > 0)
1170040         {
1170041           k_printf ("\n");
1170042         }
1170043     }
1170044 }

94.5.43   kernel/fs/zone_read.c

Si veda la sezione 93.6.37.

1180001 #include <sys/os32.h>
1180002 #include <kernel/fs.h>
1180003 #include <kernel/dev.h>
1180004 #include <errno.h>
1180005 //----------------------------------------------------------
1180006 int
1180007 zone_read (sb_t * sb, zno_t zone, void *buffer)
1180008 {
1180009   size_t size_zone;
1180010   off_t off_start;
1180011   ssize_t size_read;
1180012   // 
1180013   // Verify if the requested zone is inside the file
1180014   // system area.
1180015   // 
1180016   if (zone >= sb->zones)
1180017     {
1180018       errset (EINVAL);  // Invalid argument.
1180019       return (-1);
1180020     }
1180021   // 
1180022   // Calculate start position.
1180023   // 
1180024   size_zone = 1024 << sb->log2_size_zone;
1180025   off_start = zone;
1180026   off_start *= size_zone;
1180027   // 
1180028   // Read from device to the buffer.
1180029   // 
1180030   size_read =
1180031     dev_io ((pid_t) - 1, sb->device, DEV_READ,
1180032             off_start, buffer, size_zone, NULL);
1180033   if (size_read != size_zone)
1180034     {
1180035       errset (EIO);     // I/O error.
1180036       return (-1);
1180037     }
1180038   else
1180039     {
1180040       return (0);
1180041     }
1180042 }

94.5.44   kernel/fs/zone_write.c

Si veda la sezione 93.6.37.

1190001 #include <kernel/fs.h>
1190002 #include <kernel/dev.h>
1190003 #include <errno.h>
1190004 //----------------------------------------------------------
1190005 int
1190006 zone_write (sb_t * sb, zno_t zone, void *buffer)
1190007 {
1190008   size_t size_zone;
1190009   off_t off_start;
1190010   ssize_t size_written;
1190011   // 
1190012   // Verify if write is allowed.
1190013   // 
1190014   if (sb->options & MOUNT_RO)
1190015     {
1190016       errset (EROFS);   // Read-only file system.
1190017       return (-1);
1190018     }
1190019   // 
1190020   // Verify if the requested zone is inside the file
1190021   // system area.
1190022   // 
1190023   if (zone >= sb->zones)
1190024     {
1190025       errset (EINVAL);  // Invalid argument.
1190026       return (-1);
1190027     }
1190028   // 
1190029   // Write is allowed: calculate start position.
1190030   // 
1190031   size_zone = 1024 << sb->log2_size_zone;
1190032   off_start = zone;
1190033   off_start *= size_zone;
1190034   // 
1190035   // Write the buffer to the device.
1190036   // 
1190037   size_written =
1190038     dev_io ((pid_t) - 1, sb->device, DEV_WRITE,
1190039             off_start, buffer, size_zone, NULL);
1190040   if (size_written != size_zone)
1190041     {
1190042       errset (EIO);     // I/O error.
1190043       return (-1);
1190044     }
1190045   else
1190046     {
1190047       return (0);
1190048     }
1190049 }

94.6   os32: «kernel/ibm_i386.h»

Si veda la sezione 93.7.

1200001 #ifndef _KERNEL_IBM_I386_H
1200002 #define _KERNEL_IBM_I386_H   1
1200003 //----------------------------------------------------------
1200004 #include <stdint.h>
1200005 #include <inttypes.h>
1200006 #include <stdbool.h>
1200007 #include <stdarg.h>
1200008 //----------------------------------------------------------
1200009 // GDT
1200010 //----------------------------------------------------------
1200011 #define GDT_ITEMS       256     // Max is 8192 items.
1200012 //
1200013 typedef struct
1200014 {
1200015   uint32_t limit_a:16, base_a:16;
1200016   uint32_t base_b:8,
1200017     accessed:1,
1200018     write_execute:1,
1200019     expansion_conforming:1,
1200020     code_or_data:1,
1200021     code_data_or_system:1,
1200022     dpl:2,
1200023     present:1,
1200024     limit_b:4,
1200025     available:1, reserved:1, big:1, granularity:1, base_c:8;
1200026 } gdt_t;
1200027 //
1200028 extern gdt_t gdt_table[GDT_ITEMS];
1200029 //----------------------------------------------------------
1200030 typedef struct
1200031 {
1200032   uint16_t limit;
1200033   uint32_t base;
1200034 } __attribute__ ((packed)) gdtr_t;      // [1]
1200035 //
1200036 extern gdtr_t gdt_register;
1200037 //
1200038 // [1] It is necessary that the structure be compact,
1200039 //     so that it uses exactly 48 bits. That is why the
1200040 //     attribute `packed' for the GNU C compiler is
1200041 //     used.
1200042 //----------------------------------------------------------
1200043 int gdt_segment (int segment, uint32_t base,
1200044                  uint32_t limit, bool present,
1200045                  bool code, unsigned char dpl);
1200046 //
1200047 void gdt_print (void *gdtr, unsigned int first,
1200048                 unsigned int last);
1200049 void gdt_load (void *gdtr);
1200050 void gdt (void);
1200051 //
1200052 // Segment 0 is not used,
1200053 // segment 1 is for kernel code,
1200054 // segment 2 is for kernel data,
1200055 // segment 3 is for process 1 code,
1200056 // segment 4 is for process 1 data,
1200057 // ...
1200058 //
1200059 #define gdt_pid_to_segment_text(p)  (p*2+1)
1200060 #define gdt_pid_to_segment_data(p)  (p*2+2)
1200061 #define gdt_segment_text_to_pid(s)  (s/2)
1200062 #define gdt_segment_data_to_pid(s)  (s/2-1)
1200063 //----------------------------------------------------------
1200064 // IDT
1200065 //----------------------------------------------------------
1200066 #define IDT_ITEMS      129      // 0-128 0x00-0x80
1200067 //----------------------------------------------------------
1200068 typedef struct
1200069 {
1200070   uint32_t offset_a:16, selector:16;
1200071   uint32_t filler:8,
1200072     type:4, system:1, dpl:2, present:1, offset_b:16;
1200073 } idt_t;
1200074 //
1200075 extern idt_t idt_table[IDT_ITEMS];
1200076 //----------------------------------------------------------
1200077 typedef struct
1200078 {
1200079   uint16_t limit;
1200080   uint32_t base;
1200081 } __attribute__ ((packed)) idtr_t;
1200082 //
1200083 extern idtr_t idt_register;
1200084 //----------------------------------------------------------
1200085 void idt_descriptor (int desc, void *isr,
1200086                      uint16_t selector, bool present,
1200087                      char type, char dpl);
1200088 void idt_load (void *idtr);
1200089 void idt (void);
1200090 void idt_irq_remap (unsigned int offset_1,
1200091                     unsigned int offset_2);
1200092 void idt_print (void *idtr, unsigned int first,
1200093                 unsigned int last);
1200094 //----------------------------------------------------------
1200095 // ISR
1200096 //----------------------------------------------------------
1200097 void isr_0 (void);
1200098 void isr_1 (void);
1200099 void isr_2 (void);
1200100 void isr_3 (void);
1200101 void isr_4 (void);
1200102 void isr_5 (void);
1200103 void isr_6 (void);
1200104 void isr_7 (void);
1200105 void isr_8 (void);
1200106 void isr_9 (void);
1200107 void isr_10 (void);
1200108 void isr_11 (void);
1200109 void isr_12 (void);
1200110 void isr_13 (void);
1200111 void isr_14 (void);
1200112 void isr_15 (void);
1200113 void isr_16 (void);
1200114 void isr_17 (void);
1200115 void isr_18 (void);
1200116 void isr_19 (void);
1200117 void isr_20 (void);
1200118 void isr_21 (void);
1200119 void isr_22 (void);
1200120 void isr_23 (void);
1200121 void isr_24 (void);
1200122 void isr_25 (void);
1200123 void isr_26 (void);
1200124 void isr_27 (void);
1200125 void isr_28 (void);
1200126 void isr_29 (void);
1200127 void isr_30 (void);
1200128 void isr_31 (void);
1200129 void isr_32 (void);
1200130 void isr_33 (void);
1200131 void isr_34 (void);
1200132 void isr_35 (void);
1200133 void isr_36 (void);
1200134 void isr_37 (void);
1200135 void isr_38 (void);
1200136 void isr_39 (void);
1200137 void isr_40 (void);
1200138 void isr_41 (void);
1200139 void isr_42 (void);
1200140 void isr_43 (void);
1200141 void isr_44 (void);
1200142 void isr_45 (void);
1200143 void isr_46 (void);
1200144 void isr_47 (void);
1200145 void isr_128 (void);
1200146 //
1200147 char *isr_exception_name (int exception);
1200148 //
1200149 void isr_exception_unrecoverable (uint32_t eax,
1200150                                   uint32_t ecx,
1200151                                   uint32_t edx,
1200152                                   uint32_t ebx,
1200153                                   uint32_t ebp,
1200154                                   uint32_t esi,
1200155                                   uint32_t edi,
1200156                                   uint32_t ds,
1200157                                   uint32_t es,
1200158                                   uint32_t fs,
1200159                                   uint32_t gs,
1200160                                   uint32_t interrupt,
1200161                                   uint32_t error,
1200162                                   uint32_t eip,
1200163                                   uint32_t cs,
1200164                                   uint32_t eflags);
1200165 //
1200166 void isr_irq_clear (uint32_t idtn);
1200167 void isr_irq_clear_pic1 (void);
1200168 void isr_irq_clear_pic2 (void);
1200169 //----------------------------------------------------------
1200170 // I/O
1200171 //----------------------------------------------------------
1200172 uint32_t _in_8 (uint32_t port);
1200173 uint32_t _in_16 (uint32_t port);
1200174 uint32_t _in_32 (uint32_t port);
1200175 void _out_8 (uint32_t port, uint32_t value);
1200176 void _out_16 (uint32_t port, uint32_t value);
1200177 void _out_32 (uint32_t port, uint32_t value);
1200178 //
1200179 #define in_8(port)  \
1200180     ((unsigned int) _in_8 ((uint32_t) port))
1200181 #define in_16(port) \
1200182     ((unsigned int) _in_16 ((uint32_t) port))
1200183 #define in_32(port) \
1200184     ((unsigned int) _in_32 ((uint32_t) port))
1200185 #define out_8(port, value) \
1200186     (_out_8 ((uint32_t) port, (uint32_t) value))
1200187 #define out_16(port, value) \
1200188     (_out_16 ((uint32_t) port, (uint32_t) value))
1200189 #define out_32(port, value) \
1200190     (_out_32 ((uint32_t) port, (uint32_t) value))
1200191 //----------------------------------------------------------
1200192 // Interrupt on/off
1200193 //----------------------------------------------------------
1200194 void cli (void);
1200195 void sti (void);
1200196 void irq_on (unsigned int irq);
1200197 void irq_off (unsigned int irq);
1200198 //----------------------------------------------------------
1200199 #endif

94.6.1   kernel/ibm_i386/_in_16.s

Si veda la sezione 93.7.

1210001 .global _in_16
1210002 #------------------------------------------------------
1210003 .section .text
1210004 #------------------------------------------------------
1210005 # Port input word.
1210006 #------------------------------------------------------
1210007 _in_16:
1210008     enter $4, $0                # 1 local variable.
1210009     pushf
1210010     pusha
1210011     .equ IN_PORT,  8            # First argument.
1210012     .equ IN_DATA, -4            # Local variable.
1210013     mov  IN_PORT(%ebp), %edx    # Copy the port number
1210014                                 # into EDX, but
1210015                                 # then only DX will be
1210016                                 # used.
1210017     mov   $0, %eax              # Reset EAX.
1210018     in    %dx,  %ax             # Read DX port  and
1210019                                 # save into AX.
1210020     mov   %eax, IN_DATA(%ebp)   # Save EAX inside the
1210021                                 # local variable.
1210022     popa
1210023     popf
1210024     mov   IN_DATA(%ebp), %eax   # Restore EAX and
1210025     leave                       # return.
1210026     ret

94.6.2   kernel/ibm_i386/_in_32.s

Si veda la sezione 93.7.

1220001 .global _in_32
1220002 #------------------------------------------------------
1220003 .section .text
1220004 #------------------------------------------------------
1220005 # Port input word.
1220006 #------------------------------------------------------
1220007 _in_32:
1220008     enter $4, $0                # 1 local variable.
1220009     pushf
1220010     pusha
1220011     .equ IN_PORT,  8            # First argument.
1220012     .equ IN_DATA, -4            # Local variable.
1220013     mov  IN_PORT(%ebp), %edx    # Copy the port number
1220014                                 # into EDX, but
1220015                                 # then only DX will be
1220016                                 # used.
1220017     mov   $0, %eax              # Reset EAX.
1220018     inl   %dx, %eax             # Read DX port  and
1220019                                 # save into EAX.
1220020     mov   %eax, IN_DATA(%ebp)   # Save EAX inside the
1220021                                 # local variable.
1220022     popa
1220023     popf
1220024     mov   IN_DATA(%ebp), %eax   # Restore EAX and
1220025     leave                       # return.
1220026     ret

94.6.3   kernel/ibm_i386/_in_8.s

Si veda la sezione 93.7.

1230001 .global _in_8
1230002 #------------------------------------------------------
1230003 .section .text
1230004 #------------------------------------------------------
1230005 # Port input byte.
1230006 #------------------------------------------------------
1230007 _in_8:
1230008     enter $4, $0                # 1 local variable.
1230009     pushf
1230010     pusha
1230011     .equ IN_PORT,  8            # First argument.
1230012     .equ IN_DATA, -4            # Local variable.
1230013     mov  IN_PORT(%ebp), %edx    # Copy the port number
1230014                                 # into EDX, but
1230015                                 # then only DX will be
1230016                                 # used.
1230017     mov   $0, %eax              # Reset EAX.
1230018     inb   %dx,  %al             # Read DX port  and
1230019                                 # save into AL.
1230020     mov   %eax, IN_DATA(%ebp)   # Save EAX inside the
1230021                                 # local variable.
1230022     popa
1230023     popf
1230024     mov   IN_DATA(%ebp), %eax   # Restore EAX and
1230025     leave                       # return.
1230026     ret

94.6.4   kernel/ibm_i386/_out_16.s

Si veda la sezione 93.7.

1240001 .global _out_16
1240002 #------------------------------------------------------
1240003 .section .text
1240004 #------------------------------------------------------
1240005 # Port output word.
1240006 #------------------------------------------------------
1240007 _out_16:
1240008     enter $0, $0                # No local variables.
1240009     pushf
1240010     pusha
1240011     .equ  OUT_PORT,  8          # First parameter.
1240012     .equ  OUT_DATA, 12          # Second parameter.
1240013     mov   OUT_PORT(%ebp), %edx  # Copy output port to
1240014                                 # EDX, but only DX
1240015                                 # will be used.
1240016     mov   OUT_DATA(%ebp), %eax  # Copy output data to
1240017                                 # EAX, but only AX
1240018                                 # will be used.
1240019     out   %ax, %dx              # Send to the port.
1240020     popa
1240021     popf
1240022     leave
1240023     ret

94.6.5   kernel/ibm_i386/_out_32.s

Si veda la sezione 93.7.

1250001 .global _out_32
1250002 #------------------------------------------------------
1250003 .section .text
1250004 #------------------------------------------------------
1250005 # Port output word.
1250006 #------------------------------------------------------
1250007 _out_32:
1250008     enter $0, $0                # No local variables.
1250009     pushf
1250010     pusha
1250011     .equ  OUT_PORT,  8          # First parameter.
1250012     .equ  OUT_DATA, 12          # Second parameter.
1250013     mov   OUT_PORT(%ebp), %edx  # Copy output port to
1250014                                 # EDX, but only DX
1250015                                 # will be used.
1250016     mov   OUT_DATA(%ebp), %eax  # Copy output data to
1250017                                 # EAX.
1250018     outl  %eax, %dx             # Send to the port.
1250019     popa
1250020     popf
1250021     leave
1250022     ret

94.6.6   kernel/ibm_i386/_out_8.s

Si veda la sezione 93.7.

1260001 .global _out_8
1260002 #------------------------------------------------------
1260003 .section .text
1260004 #------------------------------------------------------
1260005 # Port output byte.
1260006 #------------------------------------------------------
1260007 _out_8:
1260008     enter $0, $0                # No local variables.
1260009     pushf
1260010     pusha
1260011     .equ  OUT_PORT,  8          # First parameter.
1260012     .equ  OUT_DATA, 12          # Second parameter.
1260013     mov   OUT_PORT(%ebp), %edx  # Copy output port to
1260014                                 # EDX, but only DX
1260015                                 # will be used.
1260016     mov   OUT_DATA(%ebp), %eax  # Copy output data to
1260017                                 # EAX, but only AL
1260018                                 # will be used.
1260019     outb  %al, %dx              # Send to the port.
1260020     popa
1260021     popf
1260022     leave
1260023     ret

94.6.7   kernel/ibm_i386/cli.s

Si veda la sezione 93.7.

1270001 .global cli
1270002 #------------------------------------------------------
1270003 .text
1270004 #------------------------------------------------------
1270005 # Clear interrupt flag.
1270006 #------------------------------------------------------
1270007 .align 4
1270008 cli:
1270009     cli
1270010     ret

94.6.8   kernel/ibm_i386/gdt.c

Si veda la sezione 93.7.

1280001 #include <kernel/ibm_i386.h>
1280002 #include <kernel/multiboot.h>
1280003 //----------------------------------------------------------
1280004 void
1280005 gdt (void)
1280006 {
1280007   uint32_t blocks;      // Total available memory
1280008   // blocks.
1280009   // 
1280010   // Calculate memory blocks.
1280011   // 
1280012   blocks = (multiboot.mem_upper * 1024) / 4096;
1280013   // 
1280014   // Set data for GDTR register.
1280015   // 
1280016   gdt_register.limit = (sizeof (gdt_table) - 1);
1280017   gdt_register.base = (uint32_t) & gdt_table[0];
1280018   // 
1280019   // Reset items inside `gdt_table[]'.
1280020   // gdt_table[0] must be null and is not to be
1280021   // used.
1280022   // 
1280023   int i;
1280024   for (i = 0; i < GDT_ITEMS; i++)
1280025     {
1280026       gdt_segment (i, 0, 0, 0, 0, 0);
1280027     }
1280028   // 
1280029   // gdt_table[1] is for kernel code.
1280030   // It covers all the available memory, with DPL 0.
1280031   // The selector is 8+0 = 0x08+0.
1280032   // 
1280033   gdt_segment (1, 0, blocks, 1, 1, 0);
1280034   // 
1280035   // gdt_table[2] is for kernel data, including stack
1280036   // (the stack
1280037   // MUST be in the same address space of data).
1280038   // It covers all the available memory, with DPL 0.
1280039   // The selector is 16+0 = 0x10+0.
1280040   // 
1280041   gdt_segment (2, 0, blocks, 1, 0, 0);
1280042   // 
1280043   // Load the GDT table.
1280044   // 
1280045   gdt_load (&gdt_register);
1280046 }

94.6.9   kernel/ibm_i386/gdt_load.s

Si veda la sezione 93.7.

1290001 .globl  gdt_load
1290002 #
1290003 gdt_load:
1290004     enter $0, $0
1290005     .equ gdtr_pointer,  8          # Primo argomento.
1290006     mov  gdtr_pointer(%ebp), %eax  # Copia il
1290007                                    # puntatore in EAX.
1290008     leave
1290009     #
1290010     lgdt (%eax)         # Carica il registro GDTR
1290011                         # dall'indirizzo in EAX.
1290012     #
1290013     # 2 kernel data, included stack, DPL 0, covering
1290014     #   all the available
1290015     #   memory: segment selector 0x10+0.
1290016     #
1290017     mov  $16, %ax
1290018     mov  %ax, %ds
1290019     mov  %ax, %es
1290020     mov  %ax, %fs
1290021     mov  %ax, %gs
1290022     mov  %ax, %ss       # The stack MUST be in the same
1290023                         # address space of the other
1290024                         # data, to allow pointers to
1290025     #                   # work correctly.
1290026     #
1290027     # 2 kernel code, DPL 0, covering all the available
1290028     #   memory:
1290029     #   segment selector 0x08+0.
1290030     #
1290031     jmp  $8, $flush
1290032 flush:
1290033     ret

94.6.10   kernel/ibm_i386/gdt_print.c

Si veda la sezione 93.7.

1300001 #include <kernel/ibm_i386.h>
1300002 #include <kernel/lib_k.h>
1300003 //
1300004 void
1300005 gdt_print (void *gdtr, unsigned int first,
1300006            unsigned int last)
1300007 {
1300008   gdtr_t *g = gdtr;
1300009   uint32_t *p = (uint32_t *) g->base;
1300010   // 
1300011   int max = (g->limit + 1) / (sizeof (uint32_t));
1300012   int i;
1300013   // 
1300014   if (((first * 2) > max) || (first > last))
1300015     {
1300016       return;
1300017     }
1300018   // 
1300019   k_printf ("[%s] base: 0x%08" PRIX32 " limit: 0x%04"
1300020             PRIX32 "\n", __func__, g->base, g->limit);
1300021   // 
1300022   for (i = (first * 2); i < max && i <= (last * 2); i += 2)
1300023     {
1300024       k_printf ("[%4" PRIx32 "] %032" PRIb32 " %032"
1300025                 PRIb32 "\n", i / 2, p[i], p[i + 1]);
1300026     }
1300027 }

94.6.11   kernel/ibm_i386/gdt_public.c

Si veda la sezione 93.7.

1310001 #include <kernel/ibm_i386.h>
1310002 //----------------------------------------------------------
1310003 gdt_t gdt_table[GDT_ITEMS];
1310004 gdtr_t gdt_register;

94.6.12   kernel/ibm_i386/gdt_segment.c

Si veda la sezione 93.7.

1320001 #include <kernel/ibm_i386.h>
1320002 #include <errno.h>
1320003 //----------------------------------------------------------
1320004 int
1320005 gdt_segment (int segment,
1320006              uint32_t base,
1320007              uint32_t limit,
1320008              bool present, bool code, unsigned char dpl)
1320009 {
1320010   // 
1320011   // Verify if the segment is valid.
1320012   // 
1320013   if ((segment >= ((sizeof (gdt_table)) / 8))
1320014       || (segment < 0))
1320015     {
1320016       errset (EINVAL);
1320017       return (-1);
1320018     }
1320019   // 
1320020   // Limit.
1320021   // 
1320022   gdt_table[segment].limit_a = (limit & 0x0000FFFF);
1320023   gdt_table[segment].limit_b = limit / 0x10000;
1320024   // 
1320025   // Base address.
1320026   // 
1320027   gdt_table[segment].base_a = (base & 0x0000FFFF);
1320028   gdt_table[segment].base_b =
1320029     ((base / 0x10000) & 0x000000FF);
1320030   gdt_table[segment].base_c = (base / 0x1000000);
1320031   // 
1320032   // Attributes.
1320033   // 
1320034 
1320035   // 
1320036   // Internal update.
1320037   // 
1320038   gdt_table[segment].accessed = 0;
1320039   // 
1320040   // r, w, x.
1320041   // 
1320042   gdt_table[segment].write_execute = 1;
1320043   // 
1320044   // Normal and conforming.
1320045   // 
1320046   gdt_table[segment].expansion_conforming = 0;
1320047   // 
1320048   gdt_table[segment].code_or_data = code;
1320049   gdt_table[segment].code_data_or_system = 1;
1320050   gdt_table[segment].dpl = dpl;
1320051   gdt_table[segment].present = present;
1320052   gdt_table[segment].available = 0;     // 0
1320053   gdt_table[segment].reserved = 0;      // 0
1320054   gdt_table[segment].big = 1;   // 32 bit
1320055   gdt_table[segment].granularity = 1;   // 4 Kibyte
1320056   // 
1320057   return (0);
1320058 }

94.6.13   kernel/ibm_i386/idt.c

Si veda la sezione 93.7.

1330001 #include <kernel/ibm_i386.h>
1330002 //----------------------------------------------------------
1330003 void
1330004 idt (void)
1330005 {
1330006   // 
1330007   // Set necessary data for the IDTR register.
1330008   // 
1330009   idt_register.limit = (sizeof (idt_table) - 1);
1330010   idt_register.base = (uint32_t) & idt_table[0];
1330011   // 
1330012   // Reset all items inside the array `idt_table[]'.
1330013   // 
1330014   int i;
1330015   for (i = 0; i < IDT_ITEMS; i++)
1330016     {
1330017       idt_descriptor (i, 0, 0, 0, 0, 0);
1330018     }
1330019   // 
1330020   // Place hardware interrupt from IRQ 0 to IRQ 7
1330021   // starting from descriptor 32 and from IRQ 8 to
1330022   // IRQ 15 starting from descriptor 40.
1330023   // 
1330024   idt_irq_remap (32, 40);
1330025   // 
1330026   // Set the ISR routines to the items inside the IDT
1330027   // table.
1330028   // 
1330029   idt_descriptor (0, isr_0, 0x0008, 1, 0xE, 0);
1330030   idt_descriptor (1, isr_1, 0x0008, 1, 0xE, 0);
1330031   idt_descriptor (2, isr_2, 0x0008, 1, 0xE, 0);
1330032   idt_descriptor (3, isr_3, 0x0008, 1, 0xE, 0);
1330033   idt_descriptor (4, isr_4, 0x0008, 1, 0xE, 0);
1330034   idt_descriptor (5, isr_5, 0x0008, 1, 0xE, 0);
1330035   idt_descriptor (6, isr_6, 0x0008, 1, 0xE, 0);
1330036   idt_descriptor (7, isr_7, 0x0008, 1, 0xE, 0);
1330037   idt_descriptor (8, isr_8, 0x0008, 1, 0xE, 0);
1330038   idt_descriptor (9, isr_9, 0x0008, 1, 0xE, 0);
1330039   idt_descriptor (10, isr_10, 0x0008, 1, 0xE, 0);
1330040   idt_descriptor (11, isr_11, 0x0008, 1, 0xE, 0);
1330041   idt_descriptor (12, isr_12, 0x0008, 1, 0xE, 0);
1330042   idt_descriptor (13, isr_13, 0x0008, 1, 0xE, 0);
1330043   idt_descriptor (14, isr_14, 0x0008, 1, 0xE, 0);
1330044   idt_descriptor (15, isr_15, 0x0008, 1, 0xE, 0);
1330045   idt_descriptor (16, isr_16, 0x0008, 1, 0xE, 0);
1330046   idt_descriptor (17, isr_17, 0x0008, 1, 0xE, 0);
1330047   idt_descriptor (18, isr_18, 0x0008, 1, 0xE, 0);
1330048   idt_descriptor (19, isr_19, 0x0008, 1, 0xE, 0);
1330049   idt_descriptor (20, isr_20, 0x0008, 1, 0xE, 0);
1330050   idt_descriptor (21, isr_21, 0x0008, 1, 0xE, 0);
1330051   idt_descriptor (22, isr_22, 0x0008, 1, 0xE, 0);
1330052   idt_descriptor (23, isr_23, 0x0008, 1, 0xE, 0);
1330053   idt_descriptor (24, isr_24, 0x0008, 1, 0xE, 0);
1330054   idt_descriptor (25, isr_25, 0x0008, 1, 0xE, 0);
1330055   idt_descriptor (26, isr_26, 0x0008, 1, 0xE, 0);
1330056   idt_descriptor (27, isr_27, 0x0008, 1, 0xE, 0);
1330057   idt_descriptor (28, isr_28, 0x0008, 1, 0xE, 0);
1330058   idt_descriptor (29, isr_29, 0x0008, 1, 0xE, 0);
1330059   idt_descriptor (30, isr_10, 0x0008, 1, 0xE, 0);
1330060   idt_descriptor (31, isr_31, 0x0008, 1, 0xE, 0);
1330061   idt_descriptor (32, isr_32, 0x0008, 1, 0xE, 0);
1330062   idt_descriptor (33, isr_33, 0x0008, 1, 0xE, 0);
1330063   idt_descriptor (34, isr_34, 0x0008, 1, 0xE, 0);
1330064   idt_descriptor (35, isr_35, 0x0008, 1, 0xE, 0);
1330065   idt_descriptor (36, isr_36, 0x0008, 1, 0xE, 0);
1330066   idt_descriptor (37, isr_37, 0x0008, 1, 0xE, 0);
1330067   idt_descriptor (38, isr_38, 0x0008, 1, 0xE, 0);
1330068   idt_descriptor (39, isr_39, 0x0008, 1, 0xE, 0);
1330069   idt_descriptor (40, isr_40, 0x0008, 1, 0xE, 0);
1330070   idt_descriptor (41, isr_41, 0x0008, 1, 0xE, 0);
1330071   idt_descriptor (42, isr_42, 0x0008, 1, 0xE, 0);
1330072   idt_descriptor (43, isr_43, 0x0008, 1, 0xE, 0);
1330073   idt_descriptor (44, isr_44, 0x0008, 1, 0xE, 0);
1330074   idt_descriptor (45, isr_45, 0x0008, 1, 0xE, 0);
1330075   idt_descriptor (46, isr_46, 0x0008, 1, 0xE, 0);
1330076   idt_descriptor (47, isr_47, 0x0008, 1, 0xE, 0);
1330077   // 
1330078   // The following item is for the system calls.
1330079   // 
1330080   idt_descriptor (128, isr_128, 0x0008, 1, 0xE, 0);
1330081   // 
1330082   // Activate the IDT loading the IDTR register.
1330083   // 
1330084   idt_load (&idt_register);
1330085 }

94.6.14   kernel/ibm_i386/idt_descriptor.c

Si veda la sezione 93.7.

1340001 #include <kernel/ibm_i386.h>
1340002 //----------------------------------------------------------
1340003 void
1340004 idt_descriptor (int desc,
1340005                 void *isr,
1340006                 uint16_t selector,
1340007                 bool present, char type, char dpl)
1340008 {
1340009   uint32_t offset = (uint32_t) isr;
1340010   // 
1340011   // Unset reserved bits and the system bit.
1340012   // 
1340013   idt_table[desc].filler = 0;
1340014   idt_table[desc].system = 0;
1340015   // 
1340016   // Relative address.
1340017   // 
1340018   idt_table[desc].offset_a = (offset & 0x0000FFFF);
1340019   idt_table[desc].offset_b = (offset / 0x10000);
1340020   // 
1340021   // Selector.
1340022   // 
1340023   idt_table[desc].selector = selector;
1340024   // 
1340025   // Valid item?
1340026   // 
1340027   idt_table[desc].present = present;
1340028   // 
1340029   // Type (gate type).
1340030   // 
1340031   idt_table[desc].type = (type & 0x0F);
1340032   // 
1340033   // DPL.
1340034   // 
1340035   idt_table[desc].dpl = (dpl & 0x03);
1340036 }

94.6.15   kernel/ibm_i386/idt_irq_remap.c

Si veda la sezione 93.7.

1350001 #include <kernel/lib_k.h>
1350002 #include <kernel/ibm_i386.h>
1350003 //----------------------------------------------------------
1350004 #define DEBUG 0
1350005 //----------------------------------------------------------
1350006 void
1350007 idt_irq_remap (unsigned int offset_1, unsigned int offset_2)
1350008 {
1350009   // 
1350010   // PIC_P è il PIC primario o «master»;
1350011   // PIC_S è il PIC secondario o «slave».
1350012   // 
1350013   // Quando si manifesta un IRQ che riguarda il PIC
1350014   // secondario,
1350015   // il PIC primario riceve IRQ 2.
1350016   // 
1350017   // ICW = initialization command word.
1350018   // OCW = operation command word.
1350019   // 
1350020   if (DEBUG)
1350021     {
1350022       k_printf
1350023         ("[%s] PIC (programmable interrupt "
1350024          "controller) " "remap: ", __func__);
1350025     }
1350026   // 
1350027   out_8 (0x20, 0x10 + 0x01);    // Initialization:
1350028   // 0x10 means that is
1350029   out_8 (0xA0, 0x10 + 0x01);    // is ICW1; 0x01 means 
1350030   // that must
1350031   // continue up to ICW4.
1350032   if (DEBUG)
1350033     {
1350034       k_printf ("ICW1");
1350035     }
1350036   out_8 (0x21, offset_1);       // ICW2: PIC_P
1350037   // starting at
1350038   // «offset_1».
1350039   out_8 (0xA1, offset_2);       // PIC_S starting at
1350040   // «offset_2».
1350041   if (DEBUG)
1350042     {
1350043       k_printf (", ICW2");
1350044     }
1350045   out_8 (0x21, 0x04);   // ICW3 PIC_P: IRQ2 driven
1350046   // from PIC_S.
1350047   out_8 (0xA1, 0x02);   // ICW3 PIC_S: driving IRQ2
1350048   // from PIC_P.
1350049   if (DEBUG)
1350050     {
1350051       k_printf (", ICW3");
1350052     }
1350053   out_8 (0x21, 0x01);   // ICW4: si precisa solo la
1350054   // modalità
1350055   out_8 (0xA1, 0x01);   // del microprocessore; 0x01 = 
1350056   // 8086.
1350057   if (DEBUG)
1350058     {
1350059       k_printf (", ICW4");
1350060     }
1350061   out_8 (0x21, 0x00);   // OCW1: reset mask to enable
1350062   // all
1350063   out_8 (0xA1, 0x00);   // IRQ numbers.
1350064   if (DEBUG)
1350065     {
1350066       k_printf (", OCW1.\n");
1350067     }
1350068 }

94.6.16   kernel/ibm_i386/idt_load.s

Si veda la sezione 93.7.

1360001 .globl  idt_load
1360002 #
1360003 idt_load:
1360004     enter $0, $0
1360005     .equ idtr_pointer,  8          # Primo argomento.
1360006     mov  idtr_pointer(%ebp), %eax  # Copia il puntatore
1360007                                    # in EAX.
1360008     leave
1360009     #
1360010     lidt (%eax)     # Utilizza la tabella IDT a cui
1360011                     # punta EAX.
1360012     #
1360013     ret

94.6.17   kernel/ibm_i386/idt_print.c

Si veda la sezione 93.7.

1370001 #include <kernel/ibm_i386.h>
1370002 #include <kernel/lib_k.h>
1370003 //
1370004 void
1370005 idt_print (void *idtr, unsigned int first,
1370006            unsigned int last)
1370007 {
1370008   idtr_t *g = idtr;
1370009   uint32_t *p = (uint32_t *) g->base;
1370010   // 
1370011   int max = (g->limit + 1) / (sizeof (uint32_t));
1370012   int i;
1370013   // 
1370014   if (((first * 2) > max) || (first > last))
1370015     {
1370016       return;
1370017     }
1370018   // 
1370019   k_printf ("[%s] base: 0x%08" PRIX32 " limit: 0x%04"
1370020             PRIX32 "\n", __func__, g->base, g->limit);
1370021   // 
1370022   for (i = (first * 2); i < max && i <= (last * 2); i += 2)
1370023     {
1370024       k_printf ("[%4" PRIx32 "] %032" PRIb32 " %032"
1370025                 PRIb32 "\n", i / 2, p[i], p[i + 1]);
1370026     }
1370027 }

94.6.18   kernel/ibm_i386/idt_public.c

Si veda la sezione 93.7.

1380001 #include <kernel/ibm_i386.h>
1380002 //----------------------------------------------------------
1380003 idt_t idt_table[129];
1380004 idtr_t idt_register;

94.6.19   kernel/ibm_i386/irq_off.c

Si veda la sezione 93.7.

1390001 #include <kernel/ibm_i386.h>
1390002 #include <stdint.h>
1390003 //----------------------------------------------------------
1390004 void
1390005 irq_off (unsigned int irq)
1390006 {
1390007   uint32_t mask;
1390008   uint32_t status;
1390009   // 
1390010   if (irq > 15)
1390011     {
1390012       return;   // There is not such IRQ.
1390013     }
1390014   else
1390015     {
1390016       mask = ((uint32_t) 1 << irq);
1390017       // 
1390018       // IRQ from 0 to 7.
1390019       // 
1390020       status = in_8 ((uint32_t) 0x21);
1390021       status = status | mask;
1390022       out_8 ((uint32_t) 0x21, status);
1390023       // 
1390024       // IRQ from 8 to 15.
1390025       // 
1390026       status = in_8 ((uint32_t) 0xA1);
1390027       status = status | (mask >> 8);
1390028       out_8 ((uint32_t) 0xA1, status);
1390029     }
1390030 }

94.6.20   kernel/ibm_i386/irq_on.c

Si veda la sezione 93.7.

1400001 #include <kernel/ibm_i386.h>
1400002 #include <stdint.h>
1400003 //----------------------------------------------------------
1400004 void
1400005 irq_on (unsigned int irq)
1400006 {
1400007   uint32_t mask;
1400008   uint32_t status;
1400009   // 
1400010   if (irq > 15)
1400011     {
1400012       return;   // There is not such IRQ.
1400013     }
1400014   else
1400015     {
1400016       mask = ~((uint32_t) 1 << irq);
1400017       // 
1400018       // IRQ from 0 to 7.
1400019       // 
1400020       status = in_8 ((uint32_t) 0x21);
1400021       status = status & mask;
1400022       out_8 ((uint32_t) 0x21, status);
1400023       // 
1400024       // IRQ from 8 to 15.
1400025       // 
1400026       status = in_8 ((uint32_t) 0xA1);
1400027       status = status & (mask >> 8);
1400028       out_8 ((uint32_t) 0xA1, status);
1400029     }
1400030 }

94.6.21   kernel/ibm_i386/isr.s

Si veda la sezione 93.7.

1410001 .extern isr_exception_unrecoverable
1410002 .extern isr_irq_clear
1410003 .extern isr_irq_clear_pic1
1410004 .extern isr_irq_clear_pic2
1410005 .extern kbd_isr
1410006 .extern sysroutine
1410007 .extern proc_current
1410008 .extern proc_stack_segment_selector;
1410009 .extern proc_stack_pointer
1410010 .extern proc_scheduler
1410011 #.extern proc_sch_terminals
1410012 #
1410013 .global _clock_kernel
1410014 .global _clock_time
1410015 .global _ksp
1410016 #
1410017 .global isr_0
1410018 .global isr_1
1410019 .global isr_2
1410020 .global isr_3
1410021 .global isr_4
1410022 .global isr_5
1410023 .global isr_6
1410024 .global isr_7
1410025 .global isr_8
1410026 .global isr_9
1410027 .global isr_10
1410028 .global isr_11
1410029 .global isr_12
1410030 .global isr_13
1410031 .global isr_14
1410032 .global isr_15
1410033 .global isr_16
1410034 .global isr_17
1410035 .global isr_18
1410036 .global isr_19
1410037 .global isr_20
1410038 .global isr_21
1410039 .global isr_22
1410040 .global isr_23
1410041 .global isr_24
1410042 .global isr_25
1410043 .global isr_26
1410044 .global isr_27
1410045 .global isr_28
1410046 .global isr_29
1410047 .global isr_30
1410048 .global isr_31
1410049 .global isr_32
1410050 .global isr_33
1410051 .global isr_34
1410052 .global isr_35
1410053 .global isr_36
1410054 .global isr_37
1410055 .global isr_38
1410056 .global isr_39
1410057 .global isr_40
1410058 .global isr_41
1410059 .global isr_42
1410060 .global isr_43
1410061 .global isr_44
1410062 .global isr_45
1410063 .global isr_46
1410064 .global isr_47
1410065 .global isr_128
1410066 #------------------------------------------------------
1410067 .section .data
1410068 #------------------------------------------------------
1410069 proc_syscallnr:              .int   0x00000000
1410070 proc_msg_offset:             .int   0x00000000
1410071 proc_msg_size:               .int   0x00000000
1410072 proc_instruction_pointer:    .int   0x00000000
1410073 proc_back_address:           .int   0x00000000
1410074 _ksp:                        .int   0x00000000
1410075 syscall_working:             .int   0x00000000
1410076 _clock_kernel:
1410077 kticks_lo:                   .int   0x00000000
1410078 kticks_hi:                   .int   0x00000000
1410079 _clock_time:
1410080 tticks_lo:                   .int   0x00000000
1410081 tticks_hi:                   .int   0x00000000
1410082 #------------------------------------------------------
1410083 .section .text
1410084 #------------------------------------------------------
1410085 #
1410086 # Inside the stack there is already, placed by the CPU:
1410087 #   [omissis]
1410088 #   push %eflags
1410089 #   push %cs
1410090 #   push %eip
1410091 #
1410092 #------------------------------------------------------
1410093 isr_0:          # «division by zero exception»
1410094     cli
1410095     push $0     # Null error code.
1410096     push $0     # Exception number.
1410097     jmp exception_unrecoverable
1410098 #------------------------------------------------------
1410099 isr_1:          # «debug exception»
1410100     cli
1410101     push $0     # Null error code.
1410102     push $1     # Exception number.
1410103     jmp exception_unrecoverable
1410104 #------------------------------------------------------
1410105 isr_2:          # «non maskable interrupt exception»
1410106     cli
1410107     push $0     # Null error code.
1410108     push $2     # Exception number.
1410109     jmp exception_unrecoverable
1410110 #------------------------------------------------------
1410111 isr_3:          # «breakpoint exception»
1410112     cli
1410113     push $0     # Null error code.
1410114     push $3     # Exception number.
1410115     jmp exception_unrecoverable
1410116 #------------------------------------------------------
1410117 isr_4:          # «into detected overflow exception»
1410118     cli
1410119     push $0     # Null error code.
1410120     push $4     # Exception number.
1410121     jmp exception_unrecoverable
1410122 #------------------------------------------------------
1410123 isr_5:          # «out of bounds exception»
1410124     cli
1410125     push $0     # Null error code.
1410126     push $5     # Exception number.
1410127     jmp exception_unrecoverable
1410128 #------------------------------------------------------
1410129 isr_6:          # «invalid opcode exception»
1410130     cli
1410131     push $0     # Null error code.
1410132     push $6     # Exception number.
1410133     jmp exception_unrecoverable
1410134 #------------------------------------------------------
1410135 isr_7:          # «no coprocessor exception»
1410136     cli
1410137     push $0     # Null error code.
1410138     push $7     # Exception number.
1410139     jmp exception_unrecoverable
1410140 #------------------------------------------------------
1410141 isr_8:          # «double fault exception»
1410142     cli
1410143     #           # Error code already present.
1410144     push $8     # Exception number.
1410145     jmp exception_unrecoverable
1410146 #------------------------------------------------------
1410147 isr_9:          # «coprocessor segment overrun
1410148                 # exception»
1410149     cli
1410150     push $0     # Null error code.
1410151     push $9     # Exception number.
1410152     jmp exception_unrecoverable
1410153 #------------------------------------------------------
1410154 isr_10:         # «bad TSS exception»
1410155     cli
1410156     #           # Error code already present.
1410157     push $10    # Exception number.
1410158     jmp exception_unrecoverable
1410159 #------------------------------------------------------
1410160 isr_11:         # «segment not present exception»
1410161     cli
1410162     #           # Error code already present.
1410163     push $11    # Exception number.
1410164     jmp exception_unrecoverable
1410165 #------------------------------------------------------
1410166 isr_12:         # «stack fault exception»
1410167     cli
1410168     #           # Error code already present.
1410169     push $12    # Exception number.
1410170     jmp exception_unrecoverable
1410171 #------------------------------------------------------
1410172 isr_13:         # «general protection fault exception»
1410173     cli
1410174     #           # Error code already present.
1410175     push $13    # Exception number.
1410176     jmp exception_unrecoverable
1410177 #------------------------------------------------------
1410178 isr_14:         # «page fault exception»
1410179     cli
1410180     #           # Error code already present.
1410181     push $14    # Exception number.
1410182     jmp exception_unrecoverable
1410183 #------------------------------------------------------
1410184 isr_15:         # «unknown interrupt exception»
1410185     cli
1410186     push $0     # Null error code.
1410187     push $15    # Exception number.
1410188     jmp exception_unrecoverable
1410189 #------------------------------------------------------
1410190 isr_16:         # «coprocessor fault exception»
1410191     cli
1410192     push $0     # Null error code.
1410193     push $16    # Exception number.
1410194     jmp exception_unrecoverable
1410195 #------------------------------------------------------
1410196 isr_17:         # «alignment check exception»
1410197     cli
1410198     push $0     # Null error code.
1410199     push $17    # Exception number.
1410200     jmp exception_unrecoverable
1410201 #------------------------------------------------------
1410202 isr_18:         # «machine check exception»
1410203     cli
1410204     push $0     # Null error code.
1410205     push $18    # Exception number.
1410206     jmp exception_unrecoverable
1410207 #------------------------------------------------------
1410208 isr_19:         # «reserved exception»
1410209     cli
1410210     push $0     # Null error code.
1410211     push $19    # Exception number.
1410212     jmp exception_unrecoverable
1410213 #------------------------------------------------------
1410214 isr_20:         # «reserved exception»
1410215     cli
1410216     push $0     # Null error code.
1410217     push $20    # Exception number.
1410218     jmp exception_unrecoverable
1410219 #------------------------------------------------------
1410220 isr_21:         # «reserved exception»
1410221     cli
1410222     push $0     # Null error code.
1410223     push $21    # Exception number.
1410224     jmp exception_unrecoverable
1410225 #------------------------------------------------------
1410226 isr_22:         # «reserved exception»
1410227     cli
1410228     push $0     # Null error code.
1410229     push $22    # Exception number.
1410230     jmp exception_unrecoverable
1410231 #------------------------------------------------------
1410232 isr_23:         # «reserved exception»
1410233     cli
1410234     push $0     # Null error code.
1410235     push $23    # Exception number.
1410236     jmp exception_unrecoverable
1410237 #------------------------------------------------------
1410238 isr_24:         # «reserved exception»
1410239     cli
1410240     push $0     # Null error code.
1410241     push $24    # Exception number.
1410242     jmp exception_unrecoverable
1410243 #------------------------------------------------------
1410244 isr_25:         # «reserved exception»
1410245     cli
1410246     push $0     # Null error code.
1410247     push $25    # Exception number.
1410248     jmp exception_unrecoverable
1410249 #------------------------------------------------------
1410250 isr_26:         # «reserved exception»
1410251     cli
1410252     push $0     # Null error code.
1410253     push $26    # Exception number.
1410254     jmp exception_unrecoverable
1410255 #------------------------------------------------------
1410256 isr_27:         # «reserved exception»
1410257     cli
1410258     push $0     # Null error code.
1410259     push $27    # Exception number.
1410260     jmp exception_unrecoverable
1410261 #------------------------------------------------------
1410262 isr_28:         # «reserved exception»
1410263     cli
1410264     push $0     # Null error code.
1410265     push $28    # Exception number.
1410266     jmp exception_unrecoverable
1410267 #------------------------------------------------------
1410268 isr_29:         # «reserved exception»
1410269     cli
1410270     push $0     # Null error code.
1410271     push $29    # Exception number.
1410272     jmp exception_unrecoverable
1410273 #------------------------------------------------------
1410274 isr_30:         # «reserved exception»
1410275     cli
1410276     push $0     # Null error code.
1410277     push $30    # Exception number.
1410278     jmp exception_unrecoverable
1410279 #------------------------------------------------------
1410280 isr_31:         # «reserved exception»
1410281     cli
1410282     push $0     # Null error code.
1410283     push $31    # Exception number.
1410284     jmp exception_unrecoverable
1410285 #------------------------------------------------------
1410286 isr_32:         # IRQ 0: «timer»
1410287     cli
1410288     jmp irq_timer
1410289 #------------------------------------------------------
1410290 isr_33:         # IRQ 1: tastiera
1410291     cli
1410292     jmp irq_keyboard
1410293 #------------------------------------------------------
1410294 isr_34:         # IRQ 2: it is fired for IRQ 8 to 15.
1410295     cli
1410296     #
1410297     # IRQ 2 must be ON inside the file
1410298     # `kernel/proc/proc_init.c', so
1410299     # that it is guaranteed that the PIC 1 is reset
1410300     # here.
1410301     #
1410302     call isr_irq_clear_pic1
1410303     #
1410304     # For IRQ 2 there is nothing else to do, because it
1410305     # is a link to the PIC 2 (IRQ 8 to 15).
1410306     #
1410307     iret
1410308 #------------------------------------------------------
1410309 isr_35:         # IRQ 3 
1410310     cli
1410311     jmp irq_pic1
1410312 #------------------------------------------------------
1410313 isr_36:         # IRQ 4
1410314     cli
1410315     jmp irq_pic1
1410316 #------------------------------------------------------
1410317 isr_37:         # IRQ 5
1410318     cli
1410319     jmp irq_pic1
1410320 #------------------------------------------------------
1410321 isr_38:         # IRQ 6: floppy disk drive
1410322     cli
1410323     jmp irq_pic1
1410324 #------------------------------------------------------
1410325 isr_39:         # IRQ 7: LPT 1
1410326     cli
1410327     jmp irq_pic1
1410328 #------------------------------------------------------
1410329 isr_40:         # IRQ 8: «real time clock (RTC)»
1410330     cli
1410331     jmp irq_pic2
1410332 #------------------------------------------------------
1410333 isr_41:         # IRQ 9
1410334     cli
1410335     jmp irq_pic2
1410336 #------------------------------------------------------
1410337 isr_42:         # IRQ 10
1410338     cli
1410339     jmp irq_pic2
1410340 #------------------------------------------------------
1410341 isr_43:         # IRQ 11
1410342     cli
1410343     jmp irq_pic2
1410344 #------------------------------------------------------
1410345 isr_44:         # IRQ 12: mouse PS/2
1410346     cli
1410347     jmp irq_pic2
1410348 #------------------------------------------------------
1410349 isr_45:         # IRQ 13: math coprocessor
1410350     cli
1410351     jmp irq_pic2
1410352 #------------------------------------------------------
1410353 isr_46:         # IRQ 14: primary IDE channel
1410354     cli
1410355     jmp irq_pic2
1410356 #------------------------------------------------------
1410357 isr_47:         # IRQ 15: secondary IDE channel
1410358     cli
1410359     jmp irq_pic2
1410360 #------------------------------------------------------
1410361 #
1410362 # Unrecoverable exceptions.
1410363 #
1410364 exception_unrecoverable:
1410365     #
1410366     # Previous pushes:
1410367     #   [omissis]
1410368     #   push %eflags
1410369     #   push %cs
1410370     #   push %eip
1410371     #
1410372     #   push $<error_number>
1410373     #   push $<idt_item_number>
1410374     #
1410375     pushl %gs
1410376     pushl %fs
1410377     pushl %es
1410378     pushl %ds
1410379     pushl %edi
1410380     pushl %esi
1410381     pushl %ebp
1410382     pushl %ebx
1410383     pushl %edx
1410384     pushl %ecx
1410385     pushl %eax
1410386     #
1410387     call isr_exception_unrecoverable
1410388     #
1410389     popl %eax
1410390     popl %ecx
1410391     popl %edx
1410392     popl %ebx
1410393     popl %ebp
1410394     popl %esi
1410395     popl %edi
1410396     popl %ds
1410397     popl %es
1410398     popl %fs
1410399     popl %gs
1410400     #
1410401     # Remove the IDT item number and the error code.
1410402     #
1410403     add $4, %esp
1410404     add $4, %esp
1410405     #
1410406     # Return from interrupt.
1410407     #
1410408     iret
1410409 #------------------------------------------------------
1410410 #
1410411 # Unspecified IRQ. Currently unused.
1410412 #
1410413 irq:
1410414     #
1410415     # Previous pushes:
1410416     #   [omissis]
1410417     #   push %eflags
1410418     #   push %cs
1410419     #   push %eip
1410420     #
1410421     #   push $0
1410422     #   push $<idt_item_number>
1410423     #
1410424     call isr_irq_clear
1410425     #
1410426     # Remove the IDT item number and the null error
1410427     # code.
1410428     #
1410429     add $4, %esp
1410430     add $4, %esp
1410431     #
1410432     # Return from interrupt.
1410433     #
1410434     iret
1410435 #------------------------------------------------------
1410436 #
1410437 # Keyboard IRQ.
1410438 #
1410439 irq_keyboard:
1410440     #
1410441     # Previous pushes:
1410442     #   [omissis]
1410443     #   push %eflags
1410444     #   push %cs
1410445     #   push %eip
1410446     #
1410447     pushl %gs
1410448     pushl %fs
1410449     pushl %es
1410450     pushl %ds
1410451     pushl %edi
1410452     pushl %esi
1410453     pushl %ebp
1410454     pushl %ebx
1410455     pushl %edx
1410456     pushl %ecx
1410457     pushl %eax
1410458     #
1410459     # Set the data segments to the kernel data segment,
1410460     # so that the following variables can be accessed.
1410461     #
1410462     mov  $16, %ax # DS, ES, FS and GS.
1410463     mov  %ax, %ds
1410464     mov  %ax, %es
1410465     mov  %ax, %fs
1410466     mov  %ax, %gs
1410467     #
1410468     # Check if a system call is already working: if so,
1410469     # just leave (go to L1).
1410470     #
1410471     cmpl $1, syscall_working
1410472     je L1
1410473     #
1410474     # Call the keyboard handler.
1410475     #
1410476     call kbd_isr
1410477     #
1410478 L1: # Restore original registers and return.
1410479     #
1410480     jmp irq_pic1_pop_iret
1410481 #------------------------------------------------------
1410482 #
1410483 # Generic IRQ from PIC 1
1410484 #
1410485 irq_pic1:
1410486     #
1410487     # Previous pushes:
1410488     #   [omissis]
1410489     #   push %eflags
1410490     #   push %cs
1410491     #   push %eip
1410492     #
1410493     pushl %gs
1410494     pushl %fs
1410495     pushl %es
1410496     pushl %ds
1410497     pushl %edi
1410498     pushl %esi
1410499     pushl %ebp
1410500     pushl %ebx
1410501     pushl %edx
1410502     pushl %ecx
1410503     pushl %eax
1410504     #
1410505     # Set the data segments to the kernel data segment,
1410506     # so that the following variables can be accessed.
1410507     #
1410508     mov  $16, %ax # DS, ES, FS and GS.
1410509     mov  %ax, %ds
1410510     mov  %ax, %es
1410511     mov  %ax, %fs
1410512     mov  %ax, %gs
1410513     #
1410514     # Check if a system call is already working: if so,
1410515     # just leave (go to L2).
1410516     #
1410517     cmpl $1, syscall_working
1410518     je L2
1410519     #
1410520     # If we are here, no system call is working and a
1410521     # user process was interrupted.
1410522     # Save process stack registers into kernel data
1410523     # segment.
1410524     #
1410525     mov %ss,  proc_stack_segment_selector
1410526     mov %esp, proc_stack_pointer
1410527     #
1410528     # Check if it is already in kernel mode: the kernel
1410529     # has PID 0.
1410530     # If so, just leave (go to L2).
1410531     #
1410532     mov proc_current, %edx       # Interrupted PID.
1410533     mov $0,           %eax       # Kernel PID.
1410534     cmp %eax, %edx
1410535     je L5
1410536     #
1410537     # If we are here, a user process was interrupted.
1410538     # Switch to the kernel stack (data segment
1410539     # descriptor).
1410540     #
1410541     mov $16, %ax
1410542     mov %ax, %ss
1410543     mov _ksp, %esp
1410544     #
1410545     # Call the scheduler.
1410546     #
1410547     call proc_scheduler
1410548     #
1410549     # Restore process stack registers from kernel data
1410550     # segment.
1410551     #
1410552     mov proc_stack_segment_selector, %ss
1410553     mov proc_stack_pointer, %esp
1410554     #
1410555 L5: # Restore from process stack and return.
1410556     #
1410557     jmp irq_pic1_pop_iret
1410558 #------------------------------------------------------
1410559 #
1410560 # Generic IRQ from PIC 2
1410561 #
1410562 irq_pic2:
1410563     #
1410564     # Previous pushes:
1410565     #   [omissis]
1410566     #   push %eflags
1410567     #   push %cs
1410568     #   push %eip
1410569     #
1410570     pushl %gs
1410571     pushl %fs
1410572     pushl %es
1410573     pushl %ds
1410574     pushl %edi
1410575     pushl %esi
1410576     pushl %ebp
1410577     pushl %ebx
1410578     pushl %edx
1410579     pushl %ecx
1410580     pushl %eax
1410581     #
1410582     # Set the data segments to the kernel data segment,
1410583     # so that the following variables can be accessed.
1410584     #
1410585     mov  $16, %ax # DS, ES, FS and GS.
1410586     mov  %ax, %ds
1410587     mov  %ax, %es
1410588     mov  %ax, %fs
1410589     mov  %ax, %gs
1410590     #
1410591     # Check if a system call is already working: if so,
1410592     # just leave (go to L2).
1410593     #
1410594     cmpl $1, syscall_working
1410595     je L2
1410596     #
1410597     # If we are here, no system call is working and a
1410598     # user process was interrupted.
1410599     # Save process stack registers into kernel data
1410600     # segment.
1410601     #
1410602     mov %ss,  proc_stack_segment_selector
1410603     mov %esp, proc_stack_pointer
1410604     #
1410605     # Check if it is already in kernel mode: the kernel
1410606     # has PID 0.
1410607     # If so, just leave (go to L2).
1410608     #
1410609     mov proc_current, %edx       # Interrupted PID.
1410610     mov $0,           %eax       # Kernel PID.
1410611     cmp %eax, %edx
1410612     je L4
1410613     #
1410614     # If we are here, a user process was interrupted.
1410615     # Switch to the kernel stack (data segment
1410616     # descriptor).
1410617     #
1410618     mov $16, %ax
1410619     mov %ax, %ss
1410620     mov _ksp, %esp
1410621     #
1410622     # Call the scheduler.
1410623     #
1410624     call proc_scheduler
1410625     #
1410626     # Restore process stack registers from kernel data
1410627     # segment.
1410628     #
1410629     mov proc_stack_segment_selector, %ss
1410630     mov proc_stack_pointer, %esp
1410631     #
1410632 L4: # Restore from process stack and return.
1410633     #
1410634     jmp irq_pic2_pop_iret
1410635 #------------------------------------------------------
1410636 #
1410637 # Timer IRQ.
1410638 #
1410639 irq_timer:
1410640     #
1410641     # Previous pushes:
1410642     #   [omissis]
1410643     #   push %eflags
1410644     #   push %cs
1410645     #   push %eip
1410646     #
1410647     pushl %gs
1410648     pushl %fs
1410649     pushl %es
1410650     pushl %ds
1410651     pushl %edi
1410652     pushl %esi
1410653     pushl %ebp
1410654     pushl %ebx
1410655     pushl %edx
1410656     pushl %ecx
1410657     pushl %eax
1410658     #
1410659     # Set the data segments to the kernel data segment,
1410660     # so that the following variables can be accessed.
1410661     #
1410662     mov  $16, %ax # DS, ES, FS and GS.
1410663     mov  %ax, %ds
1410664     mov  %ax, %es
1410665     mov  %ax, %fs
1410666     mov  %ax, %gs
1410667     #
1410668     # Increment time counters, to keep time.
1410669     #
1410670     add $1, kticks_lo    # Kernel ticks counter.
1410671     adc $0, kticks_hi    #
1410672     #
1410673     add $1, tticks_lo    # Clock ticks counter.
1410674     adc $0, tticks_hi    #
1410675     #
1410676     # Check if a system call is already working: if so,
1410677     # just leave (go to L2).
1410678     #
1410679     cmpl $1, syscall_working
1410680     je L2
1410681     #
1410682     # If we are here, no system call is working and a
1410683     # user process was interrupted.
1410684     # Save process stack registers into kernel data
1410685     # segment.
1410686     #
1410687     mov %ss,  proc_stack_segment_selector
1410688     mov %esp, proc_stack_pointer
1410689     #
1410690     # Check if it is already in kernel mode: the kernel
1410691     # has PID 0.
1410692     # If so, just leave (go to L2).
1410693     #
1410694     mov proc_current, %edx       # Interrupted PID.
1410695     mov $0,           %eax       # Kernel PID.
1410696     cmp %eax, %edx
1410697     je L2
1410698     #
1410699     # If we are here, a user process was interrupted.
1410700     # Switch to the kernel stack (data segment
1410701     # descriptor).
1410702     #
1410703     mov $16, %ax
1410704     mov %ax, %ss
1410705     mov _ksp, %esp
1410706     #
1410707     # Call the scheduler.
1410708     #
1410709     call proc_scheduler
1410710     #
1410711     # Restore process stack registers from kernel data
1410712     # segment.
1410713     #
1410714     mov proc_stack_segment_selector, %ss
1410715     mov proc_stack_pointer, %esp
1410716     #
1410717 L2: # Restore from process stack and return.
1410718     #
1410719     jmp irq_pic1_pop_iret
1410720 #------------------------------------------------------
1410721 irq_pic1_pop_iret:
1410722     #
1410723     # Restore from process stack.
1410724     #
1410725     popl %eax
1410726     popl %ecx
1410727     popl %edx
1410728     popl %ebx
1410729     popl %ebp
1410730     popl %esi
1410731     popl %edi
1410732     popl %ds
1410733     popl %es
1410734     popl %fs
1410735     popl %gs
1410736     #
1410737     # End of hardware interrupt to PIC 1.
1410738     #
1410739     call isr_irq_clear_pic1
1410740     #
1410741     # Return from interrupt.
1410742     #
1410743     iret
1410744 #------------------------------------------------------
1410745 irq_pic2_pop_iret:
1410746     #
1410747     # Restore from process stack.
1410748     #
1410749     popl %eax
1410750     popl %ecx
1410751     popl %edx
1410752     popl %ebx
1410753     popl %ebp
1410754     popl %esi
1410755     popl %edi
1410756     popl %ds
1410757     popl %es
1410758     popl %fs
1410759     popl %gs
1410760     #
1410761     # End of hardware interrupt to PIC 2 and PIC1.
1410762     #
1410763     call isr_irq_clear_pic2
1410764     #
1410765     # Return from interrupt.
1410766     #
1410767     iret
1410768 #------------------------------------------------------
1410769 #
1410770 # System call.
1410771 #
1410772 isr_128:
1410773     #
1410774     # Previous pushes:
1410775     #   [omissis]
1410776     #   push message_size
1410777     #   push &message_structure
1410778     #   push syscall_number
1410779     #   push back_address   # made by a call to sys()
1410780     #   push %eflags        # made by int $128 (0x80)
1410781     #   push %cs            # made by int $128 (0x80)
1410782     #   push %eip           # made by int $128 (0x80)
1410783     #
1410784     #--------------------------------------------------
1410785     #
1410786     # Save into process stack:
1410787     #
1410788     pushl %gs
1410789     pushl %fs
1410790     pushl %es
1410791     pushl %ds
1410792     pushl %edi
1410793     pushl %esi
1410794     pushl %ebp
1410795     pushl %ebx
1410796     pushl %edx
1410797     pushl %ecx
1410798     pushl %eax
1410799     #
1410800     # Set the data segments to the kernel data segment.
1410801     #
1410802     mov  $16, %ax # DS, ES, FS and GS.
1410803     mov  %ax, %ds
1410804     mov  %ax, %es
1410805     mov  %ax, %fs
1410806     mov  %ax, %gs
1410807     #
1410808     # Tell that it is a system call.
1410809     #
1410810     movl $1, syscall_working
1410811     #
1410812     # Save process stack registers into kernel data
1410813     # segment.
1410814     #
1410815     mov %ss,  proc_stack_segment_selector
1410816     mov %esp, proc_stack_pointer
1410817     #
1410818     # Save some more data, from the system call.
1410819     #
1410820     .equ SYSCALL_NUMBER,      60
1410821     .equ MESSAGE_OFFSET,      64
1410822     .equ MESSAGE_SIZE,        68
1410823     #
1410824     mov %esp, %ebp
1410825     mov SYSCALL_NUMBER(%ebp), %eax
1410826     mov %eax, proc_syscallnr
1410827     mov MESSAGE_OFFSET(%ebp), %eax
1410828     mov %eax, proc_msg_offset
1410829     mov MESSAGE_SIZE(%ebp), %eax
1410830     mov %eax, proc_msg_size
1410831     #
1410832     # Check if it is already in kernel mode: the kernel
1410833     # has PID 0.
1410834     #
1410835     mov proc_current, %edx       # Interrupted PID.
1410836     mov $0,           %eax       # Kernel PID.
1410837     cmp %eax, %edx
1410838     jne L3
1410839     #
1410840     # It is already the kernel stack, so, the variable
1410841     # "_ksp" is aligned to current stack pointer.
1410842     # This way, the first syscall
1410843     # can work without having to set the "_ksp"
1410844     # variable to some reasonable value.
1410845     #
1410846     mov %esp, _ksp
1410847     #
1410848 L3: # Switch to the kernel stack (data segment
1410849     # descriptor).
1410850     #
1410851     mov $16, %ax
1410852     mov %ax, %ss
1410853     mov _ksp, %esp
1410854     #
1410855     # Call the external sysroutine handler.
1410856     #
1410857     push proc_msg_size
1410858     push proc_msg_offset
1410859     push proc_syscallnr
1410860     call sysroutine
1410861     add $4, %esp
1410862     add $4, %esp
1410863     add $4, %esp
1410864     #
1410865     # Restore process stack registers from kernel data
1410866     # segment.
1410867     #
1410868     mov proc_stack_segment_selector, %ss
1410869     mov proc_stack_pointer, %esp
1410870     #
1410871     # End of system call.
1410872     #
1410873     movl $0, syscall_working
1410874     #
1410875     # Restore from process stack.
1410876     #
1410877     popl %eax
1410878     popl %ecx
1410879     popl %edx
1410880     popl %ebx
1410881     popl %ebp
1410882     popl %esi
1410883     popl %edi
1410884     popl %ds
1410885     popl %es
1410886     popl %fs
1410887     popl %gs
1410888     #
1410889     # Return from interrupt.
1410890     #
1410891     iret
1410892 #------------------------------------------------------

94.6.22   kernel/ibm_i386/isr_exception_name.c

Si veda la sezione 93.7.

1420001 #include <kernel/ibm_i386.h>
1420002 //----------------------------------------------------------
1420003 char *
1420004 isr_exception_name (int exception)
1420005 {
1420006   char *description[19] = { "division by zero",
1420007     "debug",
1420008     "non maskable interrupt",
1420009     "breakpoint",
1420010     "into detected overflow",
1420011     "out of bounds",
1420012     "invalid opcode",
1420013     "no coprocessor",
1420014     "double fault",
1420015     "coprocessor segmento overrun",
1420016     "bad TSS",
1420017     "segment not present",
1420018     "stack fault",
1420019     "general protection fault",
1420020     "page fault",
1420021     "unknown interrupt",
1420022     "coprocessor fault",
1420023     "alignment check",
1420024     "machine check"
1420025   };
1420026   // 
1420027   if (exception >= 0 && exception <= 18)
1420028     {
1420029       return description[exception];
1420030     }
1420031   else
1420032     {
1420033       return "unknown";
1420034     }
1420035 }

94.6.23   kernel/ibm_i386/isr_exception_unrecoverable.c

Si veda la sezione 93.7.

1430001 #include <kernel/ibm_i386.h>
1430002 #include <kernel/lib_k.h>
1430003 #include <sys/types.h>
1430004 //----------------------------------------------------------
1430005 void
1430006 isr_exception_unrecoverable (uint32_t eax,
1430007                              uint32_t ecx,
1430008                              uint32_t edx,
1430009                              uint32_t ebx,
1430010                              uint32_t ebp,
1430011                              uint32_t esi,
1430012                              uint32_t edi, uint32_t ds,
1430013                              uint32_t es, uint32_t fs,
1430014                              uint32_t gs,
1430015                              uint32_t interrupt,
1430016                              uint32_t error,
1430017                              uint32_t eip, uint32_t cs,
1430018                              uint32_t eflags)
1430019 {
1430020   pid_t pid = cs / 8;
1430021   // 
1430022   k_printf
1430023     ("[%s] ERROR: pid: %i exception %i: \"%s\"\n",
1430024      __func__, pid, interrupt,
1430025      isr_exception_name (interrupt));
1430026   // 
1430027   // Exit the unrecoverable application.
1430028   // 
1430029   k_exit ();
1430030 }

94.6.24   kernel/ibm_i386/isr_irq_clear.c

Si veda la sezione 93.7.

1440001 #include <kernel/ibm_i386.h>
1440002 //----------------------------------------------------------
1440003 void
1440004 isr_irq_clear (uint32_t idtn)
1440005 {
1440006   int irq = idtn - 32;
1440007   // 
1440008   // Must tell the PIC (programmable interrupt
1440009   // controller).
1440010   // 
1440011   // If the IRQ number is between 8 and 15, send
1440012   // message «EOI»
1440013   // (End of IRQ) to PIC 2.
1440014   // 
1440015   if (irq >= 8)
1440016     {
1440017       out_8 (0xA0, 0x20);
1440018     }
1440019   // 
1440020   // Then send message «EOI» to PIC 1.
1440021   // 
1440022   out_8 (0x20, 0x20);
1440023 }

94.6.25   kernel/ibm_i386/isr_irq_clear_pic1.c

Si veda la sezione 93.7.

1450001 #include <kernel/ibm_i386.h>
1450002 //----------------------------------------------------------
1450003 void
1450004 isr_irq_clear_pic1 (void)
1450005 {
1450006   // 
1450007   // Send message «EOI» to PIC 1.
1450008   // 
1450009   out_8 ((uint32_t) 0x20, (uint32_t) 0x20);
1450010 }

94.6.26   kernel/ibm_i386/isr_irq_clear_pic2.c

Si veda la sezione 93.7.

1460001 #include <kernel/ibm_i386.h>
1460002 //----------------------------------------------------------
1460003 void
1460004 isr_irq_clear_pic2 (void)
1460005 {
1460006   // 
1460007   // Send message «EOI» (End of IRQ) to PIC 2.
1460008   // It must be sent after a IRQ number between 8 and
1460009   // 15, but after
1460010   // that, remember that also the PIC 1 must receive
1460011   // an «EOI» message
1460012   // (maybe with the help of `isr_irq_clear_pic1()'
1460013   // function).
1460014   // 
1460015   out_8 ((uint32_t) 0xA0, (uint32_t) 0x20);
1460016 }

94.6.27   kernel/ibm_i386/sti.s

Si veda la sezione 93.7.

1470001 .global sti
1470002 #------------------------------------------------------
1470003 .text
1470004 #------------------------------------------------------
1470005 # Set interrupt flag.
1470006 #------------------------------------------------------
1470007 .align 4
1470008 sti:
1470009     sti
1470010     ret

94.7   os32: «kernel/lib_k.h»

Si veda la sezione 93.11.

1480001 #ifndef _KERNEL_LIB_K_H
1480002 #define _KERNEL_LIB_K_H        1
1480003 //----------------------------------------------------------
1480004 #include <restrict.h>
1480005 #include <size_t.h>
1480006 #include <stdarg.h>
1480007 #include <stdint.h>
1480008 #include <time.h>
1480009 #include <unistd.h>
1480010 #include <kernel/lib_s.h>
1480011 //----------------------------------------------------------
1480012 void k_exit (void);
1480013 unsigned int k_sleep (unsigned int seconds);
1480014 int k_usleep (useconds_t usec);
1480015 char *k_gets (char *s);
1480016 void k_perror (const char *s);
1480017 int k_printf (const char *restrict format, ...);
1480018 int k_stime (time_t * timer);
1480019 int k_vprintf (const char *restrict format, va_list arg);
1480020 int k_vsprintf (char *restrict string,
1480021                 const char *restrict format, va_list arg);
1480022 //clock_t      k_clock    (void);
1480023 #define      k_clock()  (s_clock ((uid_t) 0))
1480024 #define      k_time(t)  (s_time ((pid_t) 0, t))
1480025 //----------------------------------------------------------
1480026 #endif

94.7.1   kernel/lib_k/k_exit.s

Si veda la sezione 93.11.

1490001 .global k_exit
1490002 #------------------------------------------------------
1490003 .text
1490004 #------------------------------------------------------
1490005 .align 4
1490006 k_exit:
1490007 halt:
1490008     hlt
1490009     jmp halt

94.7.2   kernel/lib_k/k_gets.c

Si veda la sezione 93.11.

1500001 #include <kernel/lib_k.h>
1500002 #include <kernel/driver/kbd.h>
1500003 //----------------------------------------------------------
1500004 char *
1500005 k_gets (char *s)
1500006 {
1500007   int i;
1500008   // 
1500009   // Legge kbd.char.
1500010   // 
1500011   for (i = 0; i < 256; i++)
1500012     {
1500013       while (kbd.key == 0)
1500014         {
1500015           // 
1500016           // Attende un carattere.
1500017           // 
1500018           ;
1500019         }
1500020       s[i] = kbd.key;
1500021       kbd.key = 0;
1500022       if (s[i] == '\n')
1500023         {
1500024           s[i] = 0;
1500025           break;
1500026         }
1500027     }
1500028   return s;
1500029 }

94.7.3   kernel/lib_k/k_perror.c

Si veda la sezione 93.11.

1510001 #include <kernel/lib_k.h>
1510002 #include <errno.h>
1510003 //----------------------------------------------------------
1510004 void
1510005 k_perror (const char *s)
1510006 {
1510007   // 
1510008   // If errno is zero, there is nothing to show.
1510009   // 
1510010   if (errno == 0)
1510011     {
1510012       return;
1510013     }
1510014   // 
1510015   // Show the string if there is one.
1510016   // 
1510017   if (s != NULL && strlen (s) > 0)
1510018     {
1510019       k_printf ("%s: ", s);
1510020     }
1510021   // 
1510022   // Show the translated error.
1510023   // 
1510024   if (errfn[0] != 0 && errln != 0)
1510025     {
1510026       k_printf ("[%s:%u:%i] %s\n",
1510027                 errfn, errln, errno, strerror (errno));
1510028     }
1510029   else
1510030     {
1510031       k_printf ("[%i] %s\n", errno, strerror (errno));
1510032     }
1510033 }

94.7.4   kernel/lib_k/k_printf.c

Si veda la sezione 93.11.

1520001 #include <stdarg.h>
1520002 #include <kernel/lib_k.h>
1520003 //----------------------------------------------------------
1520004 int
1520005 k_printf (const char *restrict format, ...)
1520006 {
1520007   va_list ap;
1520008   va_start (ap, format);
1520009   return k_vprintf (format, ap);
1520010 }

94.7.5   kernel/lib_k/k_sleep.c

Si veda la sezione 93.11.

1530001 #include <kernel/lib_k.h>
1530002 #include <kernel/lib_s.h>
1530003 #include <kernel/proc.h>
1530004 #include <time.h>
1530005 //----------------------------------------------------------
1530006 unsigned int
1530007 k_sleep (unsigned int seconds)
1530008 {
1530009   clock_t time_start;
1530010   clock_t time_now;
1530011   clock_t time_elapsed;
1530012   clock_t time = seconds * CLOCKS_PER_SEC;
1530013   unsigned long long int loops;
1530014   // 
1530015   // Calculate how many times the following loop
1530016   // should
1530017   // be run to get the requested time.
1530018   // 
1530019   loops = proc_loops_per_clock * time;
1530020   // 
1530021   // Do a wasting time loop.
1530022   // 
1530023   time_elapsed = 0;
1530024   time_start = s_clock ((pid_t) 0);
1530025   // 
1530026   // If the function `s_clock()' can help, it will
1530027   // exit even if the loop is become slow, but the
1530028   // time was correctly accounted and is elapsed.
1530029   // 
1530030   for (; time_elapsed < time && loops > 0; loops--)
1530031     {
1530032       time_now = s_clock ((pid_t) 0);
1530033       time_elapsed = time_now - time_start;
1530034     }
1530035   // 
1530036   // The sleep is always complete.
1530037   // 
1530038   return (0);
1530039 }

94.7.6   kernel/lib_k/k_stime.c

Si veda la sezione 93.11.

1540001 #include <kernel/lib_k.h>
1540002 //----------------------------------------------------------
1540003 extern clock_t _clock_time;     // uint64_t
1540004 //----------------------------------------------------------
1540005 int
1540006 k_stime (time_t * timer)
1540007 {
1540008   _clock_time = (*timer * CLOCKS_PER_SEC);
1540009   return (0);
1540010 }

94.7.7   kernel/lib_k/k_usleep.c

Si veda la sezione 93.11.

1550001 #include <kernel/lib_k.h>
1550002 #include <kernel/lib_s.h>
1550003 #include <kernel/proc.h>
1550004 #include <time.h>
1550005 #include <unistd.h>
1550006 //----------------------------------------------------------
1550007 int
1550008 k_usleep (useconds_t usec)
1550009 {
1550010   clock_t time_start;
1550011   clock_t time_now;
1550012   clock_t time_elapsed;
1550013   clock_t time;
1550014   unsigned long long int loops;
1550015   // 
1550016   // Calculate time, in terms of internal clocks
1550017   // 
1550018   if (usec < 10000000)
1550019     {
1550020       time = (usec * CLOCKS_PER_SEC) / 1000000;
1550021     }
1550022   else
1550023     {
1550024       time = (usec / 1000000) * CLOCKS_PER_SEC;
1550025     }
1550026   // 
1550027   // Fix time: if it is zero, it means that it was
1550028   // requested a sleep
1550029   // shorter than the internal clock timer impulse.
1550030   // So, if it is zero,
1550031   // correct to at least a one.
1550032   // 
1550033   if (time == 0 && usec != 0)
1550034     time = 1;
1550035   // 
1550036   // Calculate how many times the following loop
1550037   // should
1550038   // be run to get the requested time.
1550039   // 
1550040   loops = proc_loops_per_clock * time;
1550041   // 
1550042   // Do a wasting time loop.
1550043   // 
1550044   time_elapsed = 0;
1550045   time_start = s_clock ((pid_t) 0);
1550046   // 
1550047   // If the function `s_clock()' can help, it will
1550048   // exit even if the loop is become slow, but the
1550049   // time was correctly accounted and is elapsed.
1550050   // 
1550051   for (; time_elapsed < time && loops > 0; loops--)
1550052     {
1550053       time_now = s_clock ((pid_t) 0);
1550054       time_elapsed = time_now - time_start;
1550055     }
1550056   // 
1550057   // The sleep is always complete.
1550058   // 
1550059   return (0);
1550060 }

94.7.8   kernel/lib_k/k_vprintf.c

Si veda la sezione 93.11.

1560001 #include <kernel/lib_k.h>
1560002 #include <stdio.h>
1560003 #include <kernel/dev.h>
1560004 //----------------------------------------------------------
1560005 int
1560006 k_vprintf (const char *restrict format, va_list arg)
1560007 {
1560008   size_t size = BUFSIZ;
1560009   char string[BUFSIZ];
1560010   int status;
1560011   // 
1560012   // At the moment, set `string' to be a null string.
1560013   // 
1560014   string[0] = 0;
1560015   // 
1560016   // Get the string, that must be limited to `size'
1560017   // bytes.
1560018   // 
1560019   status = vsnprintf (string, size, format, arg);
1560020   // 
1560021   // 
1560022   // 
1560023   if (status < 0)
1560024     {
1560025       // 
1560026       // Variable `errno' is not updated.
1560027       // 
1560028       return (status);
1560029     }
1560030   // 
1560031   // Get size.
1560032   // 
1560033   size = status;
1560034   // 
1560035   // Write to the first console.
1560036   // 
1560037   dev_io ((pid_t) 0, DEV_CONSOLE0, DEV_WRITE,
1560038           (off_t) 0, string, size, NULL);
1560039   // 
1560040   // Return the same value obtained from `vsnprintf()'
1560041   // 
1560042   return status;
1560043 }

94.7.9   kernel/lib_k/k_vsprintf.c

Si veda la sezione 93.11.

1570001 #include <stdarg.h>
1570002 #include <kernel/lib_k.h>
1570003 #include <stdio.h>
1570004 //----------------------------------------------------------
1570005 int
1570006 k_vsprintf (char *restrict string,
1570007             const char *restrict format, va_list arg)
1570008 {
1570009   int status;
1570010   status = vsnprintf (string, BUFSIZ, format, arg);
1570011   return status;
1570012 }

94.8   os32: «kernel/lib_s.h»

Si veda la sezione 93.12.

1580001 #ifndef _KERNEL_LIB_S_H
1580002 #define _KERNEL_LIB_S_H  1
1580003 //----------------------------------------------------------
1580004 #include <sys/types.h>
1580005 #include <sys/stat.h>
1580006 #include <kernel/fs.h>
1580007 #include <sys/os32.h>
1580008 #include <stddef.h>
1580009 #include <stdint.h>
1580010 #include <time.h>
1580011 #include <termios.h>
1580012 #include <setjmp.h>
1580013 //----------------------------------------------------------
1580014 void s__exit (pid_t pid, int status);
1580015 int s_brk (pid_t pid, void *address);
1580016 void *s_sbrk (pid_t pid, intptr_t increment);
1580017 pid_t s_fork (pid_t ppid);
1580018 int s_kill (pid_t pid_killer, pid_t pid_target, int sig);
1580019 void s_longjmp (pid_t pid, jmp_buf env, int val);
1580020 int s_seteuid (pid_t pid, uid_t euid);
1580021 int s_setjmp (pid_t pid, jmp_buf env);
1580022 int s_setuid (pid_t pid, uid_t uid);
1580023 int s_setegid (pid_t pid, gid_t egid);
1580024 int s_setgid (pid_t pid, gid_t gid);
1580025 pid_t s_wait (pid_t pid, int *status);
1580026 sighandler_t s_signal (pid_t pid, int sig,
1580027                        sighandler_t handler,
1580028                        uintptr_t wrapper);
1580029 //----------------------------------------------------------
1580030 int s_chdir (pid_t pid, const char *path);
1580031 int s_chmod (pid_t pid, const char *path, mode_t mode);
1580032 int s_chown (pid_t pid, const char *path, uid_t uid,
1580033              gid_t gid);
1580034 int s_link (pid_t pid, const char *path_old,
1580035             const char *path_new);
1580036 int s_mkdir (pid_t pid, const char *path, mode_t mode);
1580037 int s_mknod (pid_t pid, const char *path, mode_t mode,
1580038              dev_t device);
1580039 int s_open (pid_t pid, const char *path, int oflags,
1580040             mode_t mode);
1580041 int s_stat (pid_t pid, const char *path,
1580042             struct stat *buffer);
1580043 int s_unlink (pid_t pid, const char *path);
1580044 //
1580045 int s_pipe (pid_t pid, int pipefd[2]);
1580046 //
1580047 int s_close (pid_t pid, int fdn);
1580048 int s_dup (pid_t pid, int fdn_old);
1580049 int s_dup2 (pid_t pid, int fdn_old, int fdn_new);
1580050 int s_fchmod (pid_t pid, int fdn, mode_t mode);
1580051 int s_fchown (pid_t pid, int fdn, uid_t uid, gid_t gid);
1580052 int s_fcntl (pid_t pid, int fdn, int cmd, int arg);
1580053 int s_fstat (pid_t pid, int fdn, struct stat *buffer);
1580054 off_t s_lseek (pid_t pid, int fdn, off_t offset,
1580055                int whence);
1580056 ssize_t s_read (pid_t pid, int fdn, void *buffer,
1580057                 size_t count);
1580058 ssize_t s_write (pid_t pid, int fdn,
1580059                  const void *buffer, size_t count);
1580060 //
1580061 int s_mount (pid_t pid, const char *path_dev,
1580062              const char *path_mnt, int options);
1580063 int s_umount (pid_t pid, const char *path_mnt);
1580064 //----------------------------------------------------------
1580065 int s_accept (pid_t pid, int sfdn,
1580066               struct sockaddr *addr, socklen_t * addrlen);
1580067 int s_bind (pid_t pid, int sfdn,
1580068             const struct sockaddr *addr, socklen_t addrlen);
1580069 int s_connect (pid_t pid, int sfdn,
1580070                const struct sockaddr *addr,
1580071                socklen_t addrlen);
1580072 int s_listen (pid_t pid, int sfdn, int backlog);
1580073 int s_socket (pid_t pid, int family, int type,
1580074               int protocol);
1580075 ssize_t s_send (pid_t pid, int sfdn,
1580076                 const void *buffer, size_t size, int flags);
1580077 ssize_t s_recv (pid_t pid, int sfdn, void *buffer,
1580078                 size_t size, int flags);
1580079 ssize_t s_recvfrom (pid_t pid, int sfdn, void *buffer,
1580080                     size_t length, int flags,
1580081                     struct sockaddr *addrfrom,
1580082                     socklen_t * addrlen);
1580083 //
1580084 int s_ipconfig (pid_t pid, int n, h_addr_t address, int m);
1580085 int s_routeadd (pid_t pid, h_addr_t destination, int m,
1580086                 h_addr_t router, int device);
1580087 int s_routedel (pid_t pid, h_addr_t destination, int m);
1580088 //----------------------------------------------------------
1580089 int s_tcgetattr (pid_t pid, int fdn,
1580090                  struct termios *termios_p);
1580091 int s_tcsetattr (pid_t pid, int fdn, int action,
1580092                  struct termios *termios_p);
1580093 //----------------------------------------------------------
1580094 clock_t s_clock (pid_t pid);    // [p]
1580095 time_t s_time (pid_t pid, time_t * timer);      // [p]
1580096 int s_stime (pid_t pid, time_t * timer);
1580097 //
1580098 // [p] The PID information, here, is not used. The
1580099 //     argument is required only for syntax coherence
1580100 //     with other functions, that do
1580101 //     system calls, inside the kernel.
1580102 //
1580103 //----------------------------------------------------------
1580104 #endif

94.8.1   kernel/lib_s/s__exit.c

Si veda la sezione 87.2.

1590001 #include <errno.h>
1590002 #include <kernel/proc.h>
1590003 #include <kernel/lib_k.h>
1590004 #include <kernel/lib_s.h>
1590005 //----------------------------------------------------------
1590006 void
1590007 s__exit (pid_t pid, int status)
1590008 {
1590009   pid_t child;
1590010   pid_t parent = proc_table[pid].ppid;
1590011   int proc_count;
1590012   pid_t extra;
1590013   int sigchld = 0;
1590014   int fdn;
1590015   tty_t *tty;
1590016   int closed;
1590017   fd_t *fd;
1590018   // 
1590019   proc_table[pid].status = PROC_ZOMBIE;
1590020   proc_table[pid].ret = status;
1590021   proc_table[pid].sig_status = 0;
1590022   proc_table[pid].sig_ignore = 0;
1590023   // 
1590024   // Close files.
1590025   // 
1590026   for (fdn = 0; fdn < OPEN_MAX; fdn++)
1590027     {
1590028       closed = s_close (pid, fdn);
1590029       // 
1590030       // Close might fail for work in progress.
1590031       // 
1590032       if (closed < 0 && errno == EINPROGRESS)
1590033         {
1590034           // 
1590035           // Should be a socket, but close badly,
1590036           // because we cannot wait.
1590037           // 
1590038           fd = fd_reference (pid, &fdn);
1590039           if (fd->file->sock != NULL)
1590040             {
1590041               fd->file->sock->active = 0;
1590042               s_close (pid, fdn);
1590043             }
1590044         }
1590045     }
1590046   // 
1590047   // Close current directory.
1590048   // 
1590049   inode_put (proc_table[pid].inode_cwd);
1590050   // 
1590051   // Close the controlling terminal, if it is a
1590052   // process leader with
1590053   // such a terminal.
1590054   // 
1590055   if (proc_table[pid].pgrp == pid
1590056       && proc_table[pid].device_tty != 0)
1590057     {
1590058       tty = tty_reference (proc_table[pid].device_tty);
1590059       // 
1590060       // Verify.
1590061       // 
1590062       if (tty == NULL)
1590063         {
1590064           // 
1590065           // Show a kernel message.
1590066           // 
1590067           k_printf
1590068             ("kernel alert: cannot find the "
1590069              "terminal item "
1590070              "for device 0x%04x!\n",
1590071              (int) proc_table[pid].device_tty);
1590072         }
1590073       else if (tty->pgrp != pid)
1590074         {
1590075           // 
1590076           // Show a kernel message.
1590077           // 
1590078           k_printf
1590079             ("kernel alert: terminal "
1590080              "device 0x%04x should "
1590081              "be associated to the "
1590082              "process group %i, but it "
1590083              "is instead related to "
1590084              "process group %i!\n",
1590085              (int) proc_table[pid].device_tty,
1590086              (int) pid, (int) tty->pgrp);
1590087         }
1590088       else
1590089         {
1590090           tty->pgrp = 0;
1590091         }
1590092     }
1590093   // 
1590094   // Data and text might share the same address space.
1590095   // If they are are on different places, then must
1590096   // verify if the text is not shared by other
1590097   // processes.
1590098   // 
1590099   if (proc_table[pid].domain_data == 0)
1590100     {
1590101       // 
1590102       // Text and data are together.
1590103       // 
1590104       mb_free (proc_table[pid].address_text,
1590105                (proc_table[pid].domain_text
1590106                 + proc_table[pid].extra_data));
1590107     }
1590108   else
1590109     {
1590110       // 
1590111       // Data is separate and is to be removed alone.
1590112       // 
1590113       mb_free (proc_table[pid].address_data,
1590114                (proc_table[pid].domain_data
1590115                 + proc_table[pid].extra_data));
1590116       // 
1590117       // Now must verify if no other process uses the
1590118       // same text
1590119       // memory.
1590120       // 
1590121       for (proc_count = 0, extra = 0;
1590122            extra < PROCESS_MAX; extra++)
1590123         {
1590124           if (proc_table[extra].status == PROC_EMPTY ||
1590125               proc_table[extra].status == PROC_ZOMBIE)
1590126             {
1590127               continue;
1590128             }
1590129           if (proc_table[pid].address_text
1590130               == proc_table[extra].address_text)
1590131             {
1590132               proc_count++;
1590133             }
1590134         }
1590135       if (proc_count == 0)
1590136         {
1590137           // 
1590138           // The code segment can be released, because 
1590139           // no other process, except the current one
1590140           // (to be closed), is using it.
1590141           // 
1590142           mb_free (proc_table[pid].address_text,
1590143                    proc_table[pid].domain_text);
1590144         }
1590145     }
1590146   // 
1590147   // Abandon children to `init' ((pid_t) 1).
1590148   // 
1590149   for (child = 1; child < PROCESS_MAX; child++)
1590150     {
1590151       if (proc_table[child].status != PROC_EMPTY
1590152           && proc_table[child].ppid == pid)
1590153         {
1590154           proc_table[child].ppid = 1;   // Son of
1590155           // `init'.
1590156           if (proc_table[child].status == PROC_ZOMBIE)
1590157             {
1590158               sigchld = 1;      // Must send a SIGCHLD 
1590159               // to `init'.
1590160             }
1590161         }
1590162     }
1590163   // 
1590164   // SIGCHLD to `init'.
1590165   // 
1590166   if (sigchld
1590167       && pid != 1
1590168       && proc_table[1].status != PROC_EMPTY
1590169       && proc_table[1].status != PROC_ZOMBIE)
1590170     {
1590171       proc_sig_on ((pid_t) 1, SIGCHLD);
1590172     }
1590173   // 
1590174   // Announce to the parent the death of its child.
1590175   // 
1590176   if (pid != parent
1590177       && proc_table[parent].status != PROC_EMPTY)
1590178     {
1590179       proc_sig_on (parent, SIGCHLD);
1590180     }
1590181 }

94.8.2   kernel/lib_s/s_accept.c

Si veda la sezione 87.3.

1600001 #include <kernel/proc.h>
1600002 #include <kernel/lib_s.h>
1600003 #include <kernel/lib_k.h>
1600004 #include <errno.h>
1600005 #include <fcntl.h>
1600006 #include <sys/socket.h>
1600007 #include <arpa/inet.h>
1600008 //----------------------------------------------------------
1600009 int
1600010 s_accept (pid_t pid, int sfdn, struct sockaddr *addr,
1600011           socklen_t * addrlen)
1600012 {
1600013   fd_t *sfd;
1600014   fd_t *sfd2;
1600015   int sfdn2;
1600016   struct sockaddr_in sa;
1600017   int q;
1600018   // 
1600019   // Get file descriptor and verify that it is a
1600020   // socket.
1600021   // 
1600022   sfd = fd_reference (pid, &sfdn);
1600023   if (sfd == NULL || sfd->file == NULL)
1600024     {
1600025       errset (EBADF);   // Bad file descriptor.
1600026       return (-1);
1600027     }
1600028   if (sfd->file->sock == NULL)
1600029     {
1600030       errset (ENOTSOCK);        // Not a socket.
1600031       return (-1);
1600032     }
1600033   // 
1600034   // The socket must be a stream.
1600035   // 
1600036   if (sfd->file->sock->type != SOCK_STREAM)
1600037     {
1600038       errset (EOPNOTSUPP);
1600039       return (-1);
1600040     }
1600041   // 
1600042   // The socket must be a TCP stream: no other stream
1600043   // types are
1600044   // available.
1600045   // 
1600046   if (sfd->file->sock->protocol != IPPROTO_TCP)
1600047     {
1600048       errset (EOPNOTSUPP);
1600049       return (-1);
1600050     }
1600051   // 
1600052   // The socket itself must be listening.
1600053   // 
1600054   if (sfd->file->sock->tcp.conn != TCP_LISTEN)
1600055     {
1600056       errset (EINVAL);
1600057       return (-1);
1600058     }
1600059   // 
1600060   // The connections must be related to the same PID.
1600061   // 
1600062   if (sfd->file->sock->tcp.listen_pid != pid)
1600063     {
1600064       k_printf
1600065         ("[%s] the connection pid %i is not the same "
1600066          "as the current pid %i!\n", __func__,
1600067          sfd->file->sock->tcp.listen_pid, pid);
1600068       errset (EUNKNOWN);
1600069       return (-1);
1600070     }
1600071   // 
1600072   // Ok: find a connected socket from the queue.
1600073   // 
1600074   for (q = 0; q < sfd->file->sock->tcp.listen_max; q++)
1600075     {
1600076       if (sfd->file->sock->tcp.listen_queue[q] != -1)
1600077         {
1600078           // 
1600079           // Found.
1600080           // 
1600081           break;
1600082         }
1600083     }
1600084   if (q >= sfd->file->sock->tcp.listen_max)
1600085     {
1600086       // 
1600087       // At the moment, there is no new connection.
1600088       // 
1600089       errset (EAGAIN);  // Try again.
1600090       return (-1);
1600091     }
1600092   // 
1600093   // Descriptor found: check it.
1600094   // 
1600095   sfdn2 = sfd->file->sock->tcp.listen_queue[q];
1600096   sfd2 = fd_reference (pid, &sfdn2);
1600097   if (sfd2 == NULL || sfd->file == NULL)
1600098     {
1600099       k_printf
1600100         ("[%s] the connected file descriptor %i "
1600101          "for process %i is not a file descriptor!",
1600102          __func__, sfdn2, pid);
1600103       errset (EBADF);   // Bad file descriptor.
1600104       return (-1);
1600105     }
1600106   if (sfd2->file->sock == NULL)
1600107     {
1600108       k_printf
1600109         ("[%s] the connected file descriptor %i "
1600110          "for process %i is not a socket!", __func__,
1600111          sfdn2, pid);
1600112       errset (ENOTSOCK);        // Not a socket.
1600113       return (-1);
1600114     }
1600115   // 
1600116   // Ok.
1600117   // 
1600118   if (addrlen != NULL && addr != NULL && *addrlen > 0)
1600119     {
1600120       sa.sin_family = AF_INET;
1600121       sa.sin_port = htons (sfd2->file->sock->rport);
1600122       sa.sin_addr.s_addr = htonl (sfd2->file->sock->raddr);
1600123       // 
1600124       memcpy (addr, &sa,
1600125               min (sizeof (sa), (size_t) * addrlen));
1600126       *addrlen = sizeof (sa);
1600127     }
1600128   // 
1600129   // Reset the queue element and return.
1600130   // 
1600131   sfd->file->sock->tcp.listen_queue[q] = -1;
1600132   return (sfdn2);
1600133 }

94.8.3   kernel/lib_s/s_bind.c

Si veda la sezione 87.4.

1610001 #include <kernel/proc.h>
1610002 #include <kernel/lib_s.h>
1610003 #include <kernel/lib_k.h>
1610004 #include <errno.h>
1610005 #include <fcntl.h>
1610006 #include <sys/socket.h>
1610007 #include <arpa/inet.h>
1610008 //----------------------------------------------------------
1610009 int
1610010 s_bind (pid_t pid, int sfdn,
1610011         const struct sockaddr *addr, socklen_t addrlen)
1610012 {
1610013   fd_t *sfd;
1610014   struct sockaddr_in *sin;
1610015   proc_t *ps = proc_reference (pid);
1610016   int i;
1610017   clock_t clock_time;
1610018   // 
1610019   // Get file descriptor and verify that it is a
1610020   // socket.
1610021   // 
1610022   sfd = fd_reference (pid, &sfdn);
1610023   if (sfd == NULL || sfd->file == NULL)
1610024     {
1610025       errset (EBADF);   // Bad file descriptor.
1610026       return (-1);
1610027     }
1610028   if (sfd->file->sock == NULL)
1610029     {
1610030       errset (ENOTSOCK);        // Not a socket.
1610031       return (-1);
1610032     }
1610033   // 
1610034   // Verify to have a valid address pointer.
1610035   // 
1610036   if (addr == NULL)
1610037     {
1610038       errset (EINVAL);
1610039       return (-1);
1610040     }
1610041   // 
1610042   // Check minimal address size.
1610043   // 
1610044   if (addrlen < sizeof (struct sockaddr))
1610045     {
1610046       errset (EINVAL);
1610047       return (-1);
1610048     }
1610049   // 
1610050   // 
1610051   // 
1610052   if (addr->sa_family == AF_INET)
1610053     {
1610054       sin = (struct sockaddr_in *) addr;
1610055       // 
1610056       // The source address might be zero, to tell
1610057       // that any local
1610058       // address is valid.
1610059       // 
1610060       // If it is a TCP/UDP protocol, must have valid
1610061       // ports.
1610062       // 
1610063       if (sfd->file->sock->protocol == IPPROTO_TCP
1610064           || sfd->file->sock->protocol == IPPROTO_UDP)
1610065         {
1610066           // 
1610067           // Local port.
1610068           // 
1610069           if (ntohs (sin->sin_port) == 0)
1610070             {
1610071               // 
1610072               // Missing the local port.
1610073               // 
1610074               errset (EADDRNOTAVAIL);
1610075               return (-1);
1610076             }
1610077           // 
1610078           // If the local port is privileged, must
1610079           // have EUID == 0.
1610080           // 
1610081           if (ntohs (sin->sin_port) < 1024)
1610082             {
1610083               if (ps->euid != 0)
1610084                 {
1610085                   // 
1610086                   // Missing privileges.
1610087                   // 
1610088                   errset (EACCES);
1610089                   return (-1);
1610090                 }
1610091             }
1610092           // 
1610093           // If the local port is not given, a default 
1610094           // one is assigned.
1610095           // 
1610096           if (sfd->file->sock->lport == 0)
1610097             {
1610098               // 
1610099               // Must find a free one.
1610100               // 
1610101               sfd->file->sock->lport = sock_free_port ();
1610102               if (sfd->file->sock->lport == 0)
1610103                 {
1610104                   // 
1610105                   // No port is available.
1610106                   // 
1610107                   errset (EAGAIN);
1610108                   return (-1);
1610109                 }
1610110             }
1610111         }
1610112       else
1610113         {
1610114           // 
1610115           // Not supported.
1610116           // 
1610117           errset (EOPNOTSUPP);
1610118           return (-1);
1610119         }
1610120       // 
1610121       // Update the socket.
1610122       // 
1610123       sfd->file->sock->family = sin->sin_family;
1610124       sfd->file->sock->laddr = ntohl (sin->sin_addr.s_addr);
1610125       sfd->file->sock->lport = ntohs (sin->sin_port);
1610126 //      sfd->file->sock->bind   = 1;
1610127       // 
1610128       // Reset read packets clock time.
1610129       // 
1610130       clock_time = s_clock (pid);
1610131       for (i = 0; i < IP_MAX_PACKETS; i++)
1610132         {
1610133           sfd->file->sock->read.clock[i] = clock_time;
1610134         }
1610135     }
1610136   else
1610137     {
1610138       // 
1610139       // Unsupported family.
1610140       // 
1610141       errset (EAFNOSUPPORT);
1610142       return (-1);
1610143     }
1610144   // 
1610145   // Ok.
1610146   // 
1610147   return (0);
1610148 }

94.8.4   kernel/lib_s/s_brk.c

Si veda la sezione 87.5.

1620001 #include <errno.h>
1620002 #include <kernel/proc.h>
1620003 #include <kernel/memory.h>
1620004 #include <kernel/lib_k.h>
1620005 #include <kernel/lib_s.h>
1620006 //----------------------------------------------------------
1620007 #define DEBUG 0
1620008 //----------------------------------------------------------
1620009 int
1620010 s_brk (pid_t pid, void *address)
1620011 {
1620012   size_t requested_size;
1620013   size_t requested_extra;
1620014   addr_t previous_address_text;
1620015   size_t previous_domain_text;
1620016   addr_t previous_address_data;
1620017   size_t previous_domain_data;
1620018   size_t previous_extra;
1620019   addr_t allocated_text;
1620020   addr_t allocated_data;
1620021   int status;
1620022   // 
1620023   // All segments start form ((void *) 0), so the new
1620024   // address requested is equivalent to the new size
1620025   // for the data segment.
1620026   // 
1620027   requested_size = (size_t) address;
1620028   // 
1620029   // Check if it is possible to get the new size:
1620030   // cannot be less
1620031   // then the original segment size.
1620032   // 
1620033   if (proc_table[pid].domain_data == 0)
1620034     {
1620035       if (proc_table[pid].domain_text > requested_size)
1620036         {
1620037           requested_extra = 0;
1620038         }
1620039       else
1620040         {
1620041           requested_extra = requested_size
1620042             - proc_table[pid].domain_text;
1620043         }
1620044     }
1620045   else
1620046     {
1620047       if (proc_table[pid].domain_data > requested_size)
1620048         {
1620049           requested_extra = 0;
1620050         }
1620051       else
1620052         {
1620053           requested_extra = requested_size
1620054             - proc_table[pid].domain_data;
1620055         }
1620056     }
1620057   // 
1620058   // Now make shure that the new value is a multiple
1620059   // of
1620060   // MEM_BLOCK_SIZE!
1620061   // 
1620062   if (requested_extra % MEM_BLOCK_SIZE)
1620063     {
1620064       requested_extra =
1620065         (((requested_extra / MEM_BLOCK_SIZE) +
1620066           1) * MEM_BLOCK_SIZE);
1620067     }
1620068   // 
1620069   // Now resize the process.
1620070   // 
1620071   if (requested_extra == proc_table[pid].extra_data)
1620072     {
1620073       // 
1620074       // Nothing have to change.
1620075       // 
1620076       return (0);
1620077     }
1620078   else if (requested_extra < proc_table[pid].extra_data)
1620079     {
1620080       // 
1620081       // Just reduce.
1620082       // 
1620083       previous_extra = proc_table[pid].extra_data;
1620084       proc_table[pid].extra_data = requested_extra;
1620085       // 
1620086       // Update process DATA segment inside the GDT
1620087       // table.
1620088       // 
1620089       if (proc_table[pid].domain_data > 0)
1620090         {
1620091           gdt_segment (gdt_pid_to_segment_data (pid),
1620092                        (uint32_t)
1620093                        proc_table[pid].address_data,
1620094                        (uint32_t) ((proc_table
1620095                                     [pid].domain_data +
1620096                                     proc_table
1620097                                     [pid].extra_data) /
1620098                                    MEM_BLOCK_SIZE), 1, 0,
1620099                        0);
1620100         }
1620101       else
1620102         {
1620103           gdt_segment (gdt_pid_to_segment_data (pid),
1620104                        (uint32_t)
1620105                        proc_table[pid].address_text,
1620106                        (uint32_t) ((proc_table
1620107                                     [pid].domain_text +
1620108                                     proc_table
1620109                                     [pid].extra_data) /
1620110                                    MEM_BLOCK_SIZE), 1, 0,
1620111                        0);
1620112         }
1620113       // 
1620114       // Release memory.
1620115       // 
1620116       if (proc_table[pid].domain_data > 0)
1620117         {
1620118           status =
1620119             mb_reduce ((proc_table[pid].address_data +
1620120                         proc_table[pid].domain_data),
1620121                        proc_table[pid].extra_data,
1620122                        previous_extra);
1620123         }
1620124       else
1620125         {
1620126           status =
1620127             mb_reduce ((proc_table[pid].address_text +
1620128                         proc_table[pid].domain_text),
1620129                        proc_table[pid].extra_data,
1620130                        previous_extra);
1620131         }
1620132       // 
1620133       if (status < 0)
1620134         {
1620135           // 
1620136           // What happened?
1620137           // 
1620138           k_perror (NULL);
1620139         }
1620140     }
1620141   else
1620142     {
1620143       // 
1620144       // A bigger size was requested. Save previous
1620145       // information.
1620146       // 
1620147       previous_address_text = proc_table[pid].address_text;
1620148       previous_domain_text = proc_table[pid].domain_text;
1620149       previous_address_data = proc_table[pid].address_data;
1620150       previous_domain_data = proc_table[pid].domain_data;
1620151       previous_extra = proc_table[pid].extra_data;
1620152       // 
1620153       // Allocate memory for text,
1620154       // if text and data are inside the same address
1620155       // space;
1620156       // otherwise only the data segment is involved.
1620157       // 
1620158       if (proc_table[pid].domain_data == 0)
1620159         {
1620160           allocated_text =
1620161             mb_alloc_size (proc_table[pid].domain_text +
1620162                            requested_extra);
1620163           // 
1620164           if (allocated_text == 0)
1620165             {
1620166               errset (ENOMEM);  // Not enough space.
1620167               return (-1);
1620168             }
1620169           // 
1620170           if (DEBUG)
1620171             {
1620172               k_printf ("%s:%i:mb_alloc_size(%zi)",
1620173                         __FILE__, __LINE__,
1620174                         (proc_table[pid].domain_text
1620175                          + requested_extra));
1620176             }
1620177         }
1620178       // 
1620179       // Allocate memory for data, if necessary.
1620180       // 
1620181       if (proc_table[pid].domain_data > 0)
1620182         {
1620183           allocated_data =
1620184             mb_alloc_size (proc_table[pid].domain_data +
1620185                            requested_extra);
1620186           // 
1620187           if (allocated_data == 0)
1620188             {
1620189               // 
1620190               // Please note that, if we are here, no
1620191               // memory
1620192               // for the text was allocated!
1620193               // 
1620194               errset (ENOMEM);  // Not enough space.
1620195               return (-1);
1620196             }
1620197           // 
1620198           if (DEBUG)
1620199             {
1620200               k_printf ("%s:%i:mb_alloc_size(%zi)",
1620201                         __FILE__, __LINE__,
1620202                         (proc_table[pid].domain_data
1620203                          + requested_extra));
1620204             }
1620205         }
1620206       // 
1620207       // Copy the process text and, data in memory: if
1620208       // size is zero, no copy is made. But the text
1620209       // is
1620210       // copied only if text and data live together.
1620211       // 
1620212       if (proc_table[pid].domain_data == 0)
1620213         {
1620214           memcpy ((void *) allocated_text,
1620215                   (void *) proc_table[pid].address_text,
1620216                   (size_t) (proc_table[pid].domain_text +
1620217                             proc_table[pid].extra_data));
1620218         }
1620219       else
1620220         {
1620221           memcpy ((void *) allocated_data,
1620222                   (void *) proc_table[pid].address_data,
1620223                   (size_t) (proc_table[pid].domain_data +
1620224                             proc_table[pid].extra_data));
1620225         }
1620226       // 
1620227       // Update process information.
1620228       // 
1620229       if (proc_table[pid].domain_data == 0)
1620230         {
1620231           proc_table[pid].address_text = allocated_text;
1620232         }
1620233       else
1620234         {
1620235           proc_table[pid].address_data = allocated_data;
1620236         }
1620237       proc_table[pid].extra_data = requested_extra;
1620238       // 
1620239       // Update process TEXT segment inside the GDT
1620240       // table.
1620241       // 
1620242       gdt_segment (gdt_pid_to_segment_text (pid),
1620243                    (uint32_t) proc_table[pid].address_text,
1620244                    (uint32_t) (proc_table[pid].domain_text /
1620245                                MEM_BLOCK_SIZE), 1, 1, 0);
1620246       // 
1620247       // Update process DATA segment inside the GDT
1620248       // table.
1620249       // 
1620250       if (proc_table[pid].domain_data > 0)
1620251         {
1620252           gdt_segment (gdt_pid_to_segment_data (pid),
1620253                        (uint32_t)
1620254                        proc_table[pid].address_data,
1620255                        (uint32_t) ((proc_table
1620256                                     [pid].domain_data +
1620257                                     proc_table
1620258                                     [pid].extra_data) /
1620259                                    MEM_BLOCK_SIZE), 1, 0,
1620260                        0);
1620261         }
1620262       else
1620263         {
1620264           gdt_segment (gdt_pid_to_segment_data (pid),
1620265                        (uint32_t)
1620266                        proc_table[pid].address_text,
1620267                        (uint32_t) ((proc_table
1620268                                     [pid].domain_text +
1620269                                     proc_table
1620270                                     [pid].extra_data) /
1620271                                    MEM_BLOCK_SIZE), 1, 0,
1620272                        0);
1620273         }
1620274       // 
1620275       // Now release the old memory!
1620276       // 
1620277       if (proc_table[pid].domain_data == 0)
1620278         {
1620279           mb_free (previous_address_text,
1620280                    previous_domain_text + previous_extra);
1620281         }
1620282       else
1620283         {
1620284           mb_free (previous_address_data,
1620285                    previous_domain_data + previous_extra);
1620286         }
1620287     }
1620288   // 
1620289   // Ok.
1620290   // 
1620291   return (0);
1620292 }

94.8.5   kernel/lib_s/s_chdir.c

Si veda la sezione 87.6.

1630001 #include <kernel/fs.h>
1630002 #include <errno.h>
1630003 #include <kernel/proc.h>
1630004 #include <kernel/lib_s.h>
1630005 //----------------------------------------------------------
1630006 int
1630007 s_chdir (pid_t pid, const char *path)
1630008 {
1630009   proc_t *ps;
1630010   inode_t *inode_directory;
1630011   int status;
1630012   char path_directory[PATH_MAX];
1630013   // 
1630014   // Get process.
1630015   // 
1630016   ps = proc_reference (pid);
1630017   // 
1630018   // The full directory path is needed.
1630019   // 
1630020   status = path_full (path, ps->path_cwd, path_directory);
1630021   if (status < 0)
1630022     {
1630023       return (-1);
1630024     }
1630025   // 
1630026   // Try to load the new directory inode.
1630027   // 
1630028   inode_directory = path_inode (pid, path_directory);
1630029   if (inode_directory == NULL)
1630030     {
1630031       // 
1630032       // Cannot access the directory: it does not
1630033       // exists or
1630034       // permissions are not sufficient. Variable
1630035       // `errno' is set by
1630036       // function `inode_directory()'.
1630037       // 
1630038       errset (errno);
1630039       return (-1);
1630040     }
1630041   // 
1630042   // Inode loaded: release the old directory and set
1630043   // the new one.
1630044   // 
1630045   inode_put (ps->inode_cwd);
1630046   // 
1630047   ps->inode_cwd = inode_directory;
1630048   strncpy (ps->path_cwd, path_directory, PATH_MAX);
1630049   // 
1630050   // Return.
1630051   // 
1630052   return (0);
1630053 }

94.8.6   kernel/lib_s/s_chmod.c

Si veda la sezione 87.7.

1640001 #include <kernel/fs.h>
1640002 #include <errno.h>
1640003 #include <kernel/proc.h>
1640004 #include <kernel/lib_s.h>
1640005 //----------------------------------------------------------
1640006 int
1640007 s_chmod (pid_t pid, const char *path, mode_t mode)
1640008 {
1640009   proc_t *ps;
1640010   inode_t *inode;
1640011   // 
1640012   // Get process.
1640013   // 
1640014   ps = proc_reference (pid);
1640015   // 
1640016   // Try to load the file inode.
1640017   // 
1640018   inode = path_inode (pid, path);
1640019   if (inode == NULL)
1640020     {
1640021       // 
1640022       // Cannot access the file: it does not exists or 
1640023       // permissions are
1640024       // not sufficient. Variable `errno' is set by
1640025       // function
1640026       // `inode_directory()'.
1640027       // 
1640028       return (-1);
1640029     }
1640030   // 
1640031   // Verify to be root or to be the owner.
1640032   // 
1640033   if (ps->euid != 0 && ps->euid != inode->uid)
1640034     {
1640035       errset (EACCES);  // Permission denied.
1640036       return (-1);
1640037     }
1640038   // 
1640039   // Update the mode: the file type is kept and the
1640040   // rest is taken form the parameter `mode'.
1640041   // 
1640042   inode->mode = (S_IFMT & inode->mode) | (~S_IFMT & mode);
1640043   // 
1640044   // Save and release the inode.
1640045   // 
1640046   inode->changed = 1;
1640047   inode_save (inode);
1640048   inode_put (inode);
1640049   // 
1640050   // Return.
1640051   // 
1640052   return (0);
1640053 }

94.8.7   kernel/lib_s/s_chown.c

Si veda la sezione 87.8.

1650001 #include <kernel/fs.h>
1650002 #include <errno.h>
1650003 #include <kernel/proc.h>
1650004 #include <kernel/lib_s.h>
1650005 //----------------------------------------------------------
1650006 int
1650007 s_chown (pid_t pid, const char *path, uid_t uid, gid_t gid)
1650008 {
1650009   proc_t *ps;
1650010   inode_t *inode;
1650011   // 
1650012   // Get process.
1650013   // 
1650014   ps = proc_reference (pid);
1650015   // 
1650016   // Must be root, as the ability to change group is
1650017   // not considered.
1650018   // 
1650019   if (ps->euid != 0)
1650020     {
1650021       errset (EPERM);   // Operation not permitted.
1650022       return (-1);
1650023     }
1650024   // 
1650025   // Try to load the file inode.
1650026   // 
1650027   inode = path_inode (pid, path);
1650028   if (inode == NULL)
1650029     {
1650030       // 
1650031       // Cannot access the file: it does not exists or 
1650032       // permissions are
1650033       // not sufficient. Variable `errno' is set by
1650034       // function
1650035       // `inode_directory()'.
1650036       // 
1650037       return (-1);
1650038     }
1650039   // 
1650040   // Update the owner and group.
1650041   // 
1650042   if (uid != -1)
1650043     {
1650044       inode->uid = uid;
1650045       inode->changed = 1;
1650046     }
1650047   if (gid != -1)
1650048     {
1650049       inode->gid = gid;
1650050       inode->changed = 1;
1650051     }
1650052   // 
1650053   // Save and release the inode.
1650054   // 
1650055   inode_save (inode);
1650056   inode_put (inode);
1650057   // 
1650058   // Return.
1650059   // 
1650060   return (0);
1650061 }

94.8.8   kernel/lib_s/s_clock.c

Si veda la sezione 87.9.

1660001 #include <kernel/lib_s.h>
1660002 //----------------------------------------------------------
1660003 extern clock_t _clock_kernel;   // uint64_t
1660004 //----------------------------------------------------------
1660005 clock_t
1660006 s_clock (pid_t pid)
1660007 {
1660008   return (_clock_kernel);
1660009 }

94.8.9   kernel/lib_s/s_close.c

Si veda la sezione 87.10.

1670001 #include <kernel/proc.h>
1670002 #include <fcntl.h>
1670003 #include <errno.h>
1670004 //----------------------------------------------------------
1670005 int
1670006 s_close (pid_t pid, int fdn)
1670007 {
1670008   fd_t *fd;
1670009   int status;
1670010   // 
1670011   // Get file descriptor.
1670012   // 
1670013   fd = fd_reference (pid, &fdn);
1670014   if (fd == NULL || fd->file == NULL
1670015       || (fd->file->inode == NULL
1670016           && fd->file->sock == NULL))
1670017     {
1670018       errset (EBADF);   // Bad file descriptor.
1670019       return (-1);
1670020     }
1670021   // 
1670022   // 
1670023   // 
1670024   if (fd->file->inode != NULL)  // Inode
1670025     {
1670026       // 
1670027       // File descriptor with inode.
1670028       // 
1670029       // If it is a pipe, some special things must be
1670030       // done.
1670031       // 
1670032       if (S_ISFIFO (fd->file->inode->mode))
1670033         {
1670034           if (fd->fl_flags & O_RDONLY)
1670035             {
1670036               fd->file->inode->pipe_ref_read--;
1670037               if (fd->file->inode->pipe_ref_read == 0)
1670038                 {
1670039                   proc_wakeup_pipe_write (fd->file->inode);
1670040                 }
1670041             }
1670042           // 
1670043           if (fd->fl_flags & O_WRONLY)
1670044             {
1670045               fd->file->inode->pipe_ref_write--;
1670046               if (fd->file->inode->pipe_ref_write == 0)
1670047                 {
1670048                   proc_wakeup_pipe_read (fd->file->inode);
1670049                 }
1670050             }
1670051         }
1670052     }
1670053   else  // Socket
1670054     {
1670055       // 
1670056       // File descriptor with socket.
1670057       // 
1670058       status = tcp_close (fd->file->sock);
1670059       if (status < 0
1670060           && (errno == EINPROGRESS || errno == EALREADY))
1670061         {
1670062           errset (errno);
1670063           return (status);
1670064         }
1670065       // 
1670066       // Otherwise, the socket is closed and can
1670067       // continue
1670068       // with the other references.
1670069       // 
1670070     }
1670071   // 
1670072   // Reduce references inside the file table item
1670073   // and remove item if it reaches zero.
1670074   // 
1670075   fd->file->references--;
1670076   if (fd->file->references == 0)
1670077     {
1670078       fd->file->oflags = 0;
1670079       fd->file->inode = NULL;
1670080       // 
1670081       // Put inode, or release the socket, because
1670082       // there are no more
1670083       // file references.
1670084       // 
1670085       if (fd->file->inode != NULL)
1670086         {
1670087           inode_put (fd->file->inode);
1670088         }
1670089       if (fd->file->sock != NULL)
1670090         {
1670091           sock_put (fd->file->sock);
1670092         }
1670093     }
1670094   // 
1670095   // Remove file descriptor.
1670096   // 
1670097   fd->fl_flags = 0;
1670098   fd->fd_flags = 0;
1670099   fd->file = NULL;
1670100   // 
1670101   // 
1670102   // 
1670103   return (0);
1670104 }

94.8.10   kernel/lib_s/s_connect.c

Si veda la sezione 87.11.

1680001 #include <kernel/proc.h>
1680002 #include <kernel/lib_s.h>
1680003 #include <kernel/lib_k.h>
1680004 #include <kernel/net/route.h>
1680005 #include <errno.h>
1680006 #include <fcntl.h>
1680007 #include <sys/socket.h>
1680008 #include <arpa/inet.h>
1680009 //----------------------------------------------------------
1680010 int
1680011 s_connect (pid_t pid, int sfdn,
1680012            const struct sockaddr *addr, socklen_t addrlen)
1680013 {
1680014   fd_t *sfd;
1680015   struct sockaddr_in *sin;
1680016   clock_t clock_time;
1680017   int i;
1680018   int status;
1680019   // 
1680020   // Get file descriptor and verify that it is a
1680021   // socket.
1680022   // 
1680023   sfd = fd_reference (pid, &sfdn);
1680024   if (sfd == NULL || sfd->file == NULL)
1680025     {
1680026       errset (EBADF);   // Bad file descriptor.
1680027       return (-1);
1680028     }
1680029   if (sfd->file->sock == NULL)
1680030     {
1680031       errset (ENOTSOCK);        // Not a socket.
1680032       return (-1);
1680033     }
1680034   // 
1680035   // Verify to have a valid address pointer.
1680036   // 
1680037   if (addr == NULL)
1680038     {
1680039       errset (EINVAL);
1680040       return (-1);
1680041     }
1680042   // 
1680043   // Check minimal address size.
1680044   // 
1680045   if (addrlen < sizeof (struct sockaddr))
1680046     {
1680047       errset (EINVAL);
1680048       return (-1);
1680049     }
1680050   // 
1680051   // 
1680052   // 
1680053   if (addr->sa_family == AF_INET)
1680054     {
1680055       sin = (struct sockaddr_in *) addr;
1680056       // 
1680057       // Check to have the destination IP address.
1680058       // 
1680059       if (sin->sin_addr.s_addr == 0)
1680060         {
1680061           // 
1680062           // This is not valid.
1680063           // 
1680064           errset (EADDRNOTAVAIL);
1680065           return (-1);
1680066         }
1680067       // 
1680068       // If it is a TCP/UDP protocol, must have valid
1680069       // ports.
1680070       // 
1680071       if (sfd->file->sock->protocol == IPPROTO_TCP
1680072           || sfd->file->sock->protocol == IPPROTO_UDP)
1680073         {
1680074           // 
1680075           // Remote port.
1680076           // 
1680077           if (sin->sin_port == 0)
1680078             {
1680079               // 
1680080               // Missing the remote port.
1680081               // 
1680082               errset (EADDRNOTAVAIL);
1680083               return (-1);
1680084             }
1680085           // 
1680086           // Local port.
1680087           // 
1680088           if (sfd->file->sock->lport == 0)
1680089             {
1680090               // 
1680091               // Must find a free one.
1680092               // 
1680093               sfd->file->sock->lport = sock_free_port ();
1680094               if (sfd->file->sock->lport == 0)
1680095                 {
1680096                   // 
1680097                   // No port is available.
1680098                   // 
1680099                   errset (EAGAIN);
1680100                   return (-1);
1680101                 }
1680102             }
1680103         }
1680104       // 
1680105       // Update the socket, but not a TCP connection
1680106       // already
1680107       // working (TCP not connected has a zeroed
1680108       // `tcp.conn' filled).
1680109       // 
1680110       if (sfd->file->sock->tcp.conn == 0
1680111           || sfd->file->sock->tcp.conn == TCP_CLOSE)
1680112         {
1680113           // 
1680114           // Update the socket.
1680115           // 
1680116           sfd->file->sock->family = sin->sin_family;
1680117           sfd->file->sock->raddr =
1680118             ntohl (sin->sin_addr.s_addr);
1680119           sfd->file->sock->rport = ntohs (sin->sin_port);
1680120           // 
1680121           // Reset read packets clock time.
1680122           // 
1680123           clock_time = s_clock (pid);
1680124           for (i = 0; i < IP_MAX_PACKETS; i++)
1680125             {
1680126               sfd->file->sock->read.clock[i] = clock_time;
1680127             }
1680128         }
1680129       else
1680130         {
1680131           // 
1680132           // It *is* a TCP connection already working: 
1680133           // verify that
1680134           // the socket is set as expected
1680135           // 
1680136           if (sfd->file->sock->family !=
1680137               sin->sin_family
1680138               || sfd->file->sock->raddr !=
1680139               ntohl (sin->sin_addr.s_addr)
1680140               || sfd->file->sock->rport !=
1680141               ntohs (sin->sin_port))
1680142             {
1680143               // 
1680144               // The socket address is changed!
1680145               // 
1680146               errset (EISCONN);
1680147               return (-1);
1680148             }
1680149         }
1680150       // 
1680151       // If it is a TCP, not already working, should
1680152       // connect.
1680153       // The function `tcp_connect()' will verify the
1680154       // connection
1680155       // status.
1680156       // 
1680157       if (sfd->file->sock->protocol == IPPROTO_TCP)
1680158         {
1680159           // 
1680160           // Be shure to have a source address.
1680161           // 
1680162           if (sfd->file->sock->laddr == 0)
1680163             {
1680164               // 
1680165               // Default source address: get the
1680166               // source address from the
1680167               // routing table, based on the
1680168               // destination.
1680169               // 
1680170               sfd->file->sock->laddr
1680171                 =
1680172                 route_remote_to_local (sfd->file->
1680173                                        sock->raddr);
1680174               if (sfd->file->sock->laddr ==
1680175                   ((h_addr_t) - 1))
1680176                 {
1680177                   errset (errno);
1680178                   return (-1);
1680179                 }
1680180             }
1680181           // 
1680182           // Call tcp_connect ().
1680183           // 
1680184           status = tcp_connect (sfd->file->sock);
1680185           if (status)
1680186             {
1680187               errset (errno);
1680188             }
1680189           return (status);
1680190         }
1680191     }
1680192   else
1680193     {
1680194       // 
1680195       // It is not AF_INET: unsupported address
1680196       // family.
1680197       // 
1680198       errset (EAFNOSUPPORT);
1680199       return (-1);
1680200     }
1680201   // 
1680202   // Ok.
1680203   // 
1680204   return (0);
1680205 }

94.8.11   kernel/lib_s/s_dup.c

Si veda la sezione 87.12.

1690001 #include <kernel/lib_s.h>
1690002 #include <kernel/fs.h>
1690003 //----------------------------------------------------------
1690004 int
1690005 s_dup (pid_t pid, int fdn_old)
1690006 {
1690007   return (fd_dup (pid, fdn_old, 0));
1690008 }

94.8.12   kernel/lib_s/s_dup2.c

Si veda la sezione 87.12.

1700001 #include <kernel/proc.h>
1700002 #include <kernel/lib_s.h>
1700003 #include <errno.h>
1700004 #include <fcntl.h>
1700005 //----------------------------------------------------------
1700006 int
1700007 s_dup2 (pid_t pid, int fdn_old, int fdn_new)
1700008 {
1700009   proc_t *ps;
1700010   int status;
1700011   // 
1700012   // Get process.
1700013   // 
1700014   ps = proc_reference (pid);
1700015   // 
1700016   // Verify if `fdn_old' is a valid value.
1700017   // 
1700018   if (fdn_old < 0 ||
1700019       fdn_old >= OPEN_MAX || ps->fd[fdn_old].file == NULL)
1700020     {
1700021       errset (EBADF);   // Bad file descriptor.
1700022       return (-1);
1700023     }
1700024   // 
1700025   // Check if `fd_old' and `fd_new' are the same.
1700026   // 
1700027   if (fdn_old == fdn_new)
1700028     {
1700029       return (fdn_new);
1700030     }
1700031   // 
1700032   // Close `fdn_new' if it is open and copy `fdn_old'
1700033   // into it.
1700034   // 
1700035   if (ps->fd[fdn_new].file != NULL)
1700036     {
1700037       status = s_close (pid, fdn_new);
1700038       if (status != 0)
1700039         {
1700040           return (-1);
1700041         }
1700042     }
1700043   ps->fd[fdn_new].fl_flags = ps->fd[fdn_old].fl_flags;
1700044   ps->fd[fdn_new].fd_flags =
1700045     ps->fd[fdn_old].fd_flags & ~FD_CLOEXEC;
1700046   ps->fd[fdn_new].file = ps->fd[fdn_old].file;
1700047   ps->fd[fdn_new].file->references++;
1700048   return (fdn_new);
1700049 }

94.8.13   kernel/lib_s/s_fchmod.c

Si veda la sezione 87.7.

1710001 #include <kernel/proc.h>
1710002 #include <kernel/lib_s.h>
1710003 #include <sys/stat.h>
1710004 #include <errno.h>
1710005 //----------------------------------------------------------
1710006 int
1710007 s_fchmod (pid_t pid, int fdn, mode_t mode)
1710008 {
1710009   proc_t *ps;
1710010   inode_t *inode;
1710011   // 
1710012   // Get process.
1710013   // 
1710014   ps = proc_reference (pid);
1710015   // 
1710016   // Verify if the file descriptor is valid.
1710017   // 
1710018   if (ps->fd[fdn].file == NULL)
1710019     {
1710020       errset (EBADF);   // Bad file descriptor.
1710021       return (-1);
1710022     }
1710023   // 
1710024   // Reach the inode.
1710025   // 
1710026   inode = ps->fd[fdn].file->inode;
1710027   // 
1710028   // If the Inode does not exist, exit with error.
1710029   // 
1710030   if (inode == NULL)
1710031     {
1710032       errset (ENOENT);
1710033       return (-1);
1710034     }
1710035   // 
1710036   // Verify to be the owner, or at least to be UID ==
1710037   // 0.
1710038   // 
1710039   if (ps->euid != inode->uid && ps->euid != 0)
1710040     {
1710041       errset (EACCES);  // Permission denied.
1710042       return (-1);
1710043     }
1710044   // 
1710045   // Update the mode: the file type is kept and the
1710046   // rest is taken form the parameter `mode'.
1710047   // 
1710048   inode->mode = (S_IFMT & inode->mode) | (~S_IFMT & mode);
1710049   // 
1710050   // Save the inode.
1710051   // 
1710052   inode->changed = 1;
1710053   inode_save (inode);
1710054   // 
1710055   // Return.
1710056   // 
1710057   return (0);
1710058 }

94.8.14   kernel/lib_s/s_fchown.c

Si veda la sezione 87.8.

1720001 #include <kernel/proc.h>
1720002 #include <kernel/lib_s.h>
1720003 #include <errno.h>
1720004 //----------------------------------------------------------
1720005 int
1720006 s_fchown (pid_t pid, int fdn, uid_t uid, gid_t gid)
1720007 {
1720008   proc_t *ps;
1720009   inode_t *inode;
1720010   // 
1720011   // Get process.
1720012   // 
1720013   ps = proc_reference (pid);
1720014   // 
1720015   // Verify if the file descriptor is valid.
1720016   // 
1720017   if (ps->fd[fdn].file == NULL)
1720018     {
1720019       errset (EBADF);   // Bad file descriptor.
1720020       return (-1);
1720021     }
1720022   // 
1720023   // Reach the inode.
1720024   // 
1720025   inode = ps->fd[fdn].file->inode;
1720026   // 
1720027   // If the Inode does not exist, exit with error.
1720028   // 
1720029   if (inode == NULL)
1720030     {
1720031       errset (ENOENT);
1720032       return (-1);
1720033     }
1720034   // 
1720035   // Verify to be root, as the ability to change group
1720036   // is not taken into consideration.
1720037   // 
1720038   if (ps->euid != 0)
1720039     {
1720040       errset (EACCES);  // Permission denied.
1720041       return (-1);
1720042     }
1720043   // 
1720044   // Update the ownership.
1720045   // 
1720046   if (uid != -1)
1720047     {
1720048       inode->uid = uid;
1720049       inode->changed = 1;
1720050     }
1720051   if (gid != -1)
1720052     {
1720053       inode->gid = gid;
1720054       inode->changed = 1;
1720055     }
1720056   // 
1720057   // Save the inode.
1720058   // 
1720059   inode->changed = 1;
1720060   inode_save (inode);
1720061   // 
1720062   // Return.
1720063   // 
1720064   return (0);
1720065 }

94.8.15   kernel/lib_s/s_fcntl.c

Si veda la sezione 87.18.

1730001 #include <kernel/proc.h>
1730002 #include <kernel/lib_s.h>
1730003 #include <kernel/fs.h>
1730004 #include <errno.h>
1730005 #include <fcntl.h>
1730006 //----------------------------------------------------------
1730007 int
1730008 s_fcntl (pid_t pid, int fdn, int cmd, int arg)
1730009 {
1730010   proc_t *ps;
1730011   int mask;
1730012   // 
1730013   // Get process.
1730014   // 
1730015   ps = proc_reference (pid);
1730016   // 
1730017   // Verify if the file descriptor is valid.
1730018   // 
1730019   if (ps->fd[fdn].file == NULL)
1730020     {
1730021       errset (EBADF);   // Bad file descriptor.
1730022       return (-1);
1730023     }
1730024   // 
1730025   // 
1730026   // 
1730027   switch (cmd)
1730028     {
1730029     case F_DUPFD:
1730030       return (fd_dup (pid, fdn, arg));
1730031       break;
1730032     case F_GETFD:
1730033       return (ps->fd[fdn].fd_flags);
1730034       break;
1730035     case F_SETFD:
1730036       ps->fd[fdn].fd_flags = arg;
1730037       return (0);
1730038     case F_GETFL:
1730039       return (ps->fd[fdn].fl_flags);
1730040     case F_SETFL:
1730041       // 
1730042       // Calculate a mask with bits that are *not* to
1730043       // be set.
1730044       // 
1730045       mask =
1730046         (O_ACCMODE | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
1730047       // 
1730048       // Set to zero the bits that are not to be set
1730049       // from
1730050       // the argument.
1730051       // 
1730052       arg = (arg & ~mask);
1730053       // 
1730054       // Set to zero the bit that *are* to be set.
1730055       // 
1730056       ps->fd[fdn].fl_flags &= mask;
1730057       // 
1730058       // Set the bits, already filtered inside the
1730059       // argument.
1730060       // 
1730061       ps->fd[fdn].fl_flags |= arg;
1730062       // 
1730063       return (0);
1730064     default:
1730065       errset (EINVAL);  // Not implemented.
1730066       return (-1);
1730067     }
1730068 }

94.8.16   kernel/lib_s/s_fork.c

Si veda la sezione 87.19.

1740001 #include <kernel/proc.h>
1740002 #include <errno.h>
1740003 #include <fcntl.h>
1740004 #include <kernel/lib_k.h>
1740005 #include <kernel/lib_s.h>
1740006 //----------------------------------------------------------
1740007 #define DEBUG 0
1740008 //----------------------------------------------------------
1740009 extern uint32_t proc_stack_pointer;
1740010 //----------------------------------------------------------
1740011 pid_t
1740012 s_fork (pid_t ppid)
1740013 {
1740014   pid_t pid;
1740015   pid_t zombie;
1740016   addr_t allocated_text = 0;
1740017   addr_t allocated_data = 0;
1740018   addr_t addr_stack_pointer = 0;
1740019   int fdn;
1740020   uint16_t segment_descriptor;
1740021   int sig;
1740022   // 
1740023   // Find a free PID.
1740024   // 
1740025   for (pid = 1; pid < PROCESS_MAX; pid++)
1740026     {
1740027       if (proc_table[pid].status == PROC_EMPTY)
1740028         {
1740029           break;
1740030         }
1740031     }
1740032   if (pid >= PROCESS_MAX)
1740033     {
1740034       // 
1740035       // There is no free pid.
1740036       // 
1740037       errset (ENOMEM);  // Not enough space.
1740038       return (-1);
1740039     }
1740040   // 
1740041   // Before allocating a new process, must check if
1740042   // there are some
1740043   // zombie slots, still with original segment data:
1740044   // should reset
1740045   // them now!
1740046   // 
1740047   for (zombie = 1; zombie < PROCESS_MAX; zombie++)
1740048     {
1740049       if (proc_table[zombie].status == PROC_ZOMBIE
1740050           && (proc_table[zombie].address_text != 0
1740051               || proc_table[zombie].domain_text != 0))
1740052         {
1740053           proc_table[zombie].address_text = (addr_t) 0;
1740054           proc_table[zombie].domain_text = (size_t) 0;
1740055           proc_table[zombie].address_data = (addr_t) 0;
1740056           proc_table[zombie].domain_data = (size_t) 0;
1740057           proc_table[zombie].domain_stack = (size_t) 0;
1740058           proc_table[zombie].extra_data = (size_t) 0;
1740059           proc_table[zombie].sp = 0;
1740060         }
1740061     }
1740062   // 
1740063   // Allocate memory for text, if text and data are
1740064   // inside
1740065   // the same address space.
1740066   // 
1740067   if (proc_table[ppid].domain_data == 0)
1740068     {
1740069       allocated_text =
1740070         mb_alloc_size (proc_table[ppid].domain_text +
1740071                        proc_table[ppid].extra_data);
1740072       // 
1740073       if (allocated_text == 0)
1740074         {
1740075           errset (ENOMEM);      // Not enough space.
1740076           return ((pid_t) - 1);
1740077         }
1740078       // 
1740079       if (DEBUG)
1740080         {
1740081           k_printf ("%s:%i:mb_alloc_size(%zi)",
1740082                     __FILE__, __LINE__,
1740083                     (proc_table[ppid].domain_text
1740084                      + proc_table[ppid].extra_data));
1740085         }
1740086     }
1740087   // 
1740088   // Allocate memory for data, if necessary.
1740089   // 
1740090   if (proc_table[ppid].domain_data > 0)
1740091     {
1740092       allocated_data =
1740093         mb_alloc_size (proc_table[ppid].domain_data +
1740094                        proc_table[ppid].extra_data);
1740095       // 
1740096       if (allocated_data == 0)
1740097         {
1740098           // 
1740099           // Please note that, if we are here, no
1740100           // memory
1740101           // for the text was allocated!
1740102           // 
1740103           errset (ENOMEM);      // Not enough space.
1740104           return ((pid_t) - 1);
1740105         }
1740106       // 
1740107       if (DEBUG)
1740108         {
1740109           k_printf ("%s:%i:mb_alloc_size(%zi)",
1740110                     __FILE__, __LINE__,
1740111                     (proc_table[ppid].domain_data
1740112                      + proc_table[ppid].extra_data));
1740113         }
1740114     }
1740115   // 
1740116   // Copy the process text and, data in memory: if
1740117   // size is zero, no copy is made. But the text is
1740118   // copied only if text and data live together.
1740119   // 
1740120   if (proc_table[ppid].domain_data == 0)
1740121     {
1740122       memcpy ((void *) allocated_text,
1740123               (void *) proc_table[ppid].address_text,
1740124               (size_t) (proc_table[ppid].domain_text
1740125                         + proc_table[ppid].extra_data));
1740126     }
1740127   else
1740128     {
1740129       memcpy ((void *) allocated_data,
1740130               (void *) proc_table[ppid].address_data,
1740131               (size_t) (proc_table[ppid].domain_data
1740132                         + proc_table[ppid].extra_data));
1740133     }
1740134   // 
1740135   // Allocate the new PID inside the `proc_table[]'.
1740136   // 
1740137   proc_table[pid].ppid = ppid;
1740138   proc_table[pid].pgrp = proc_table[ppid].pgrp;
1740139   proc_table[pid].uid = proc_table[ppid].uid;
1740140   proc_table[pid].euid = proc_table[ppid].euid;
1740141   proc_table[pid].suid = proc_table[ppid].suid;
1740142   proc_table[pid].gid = proc_table[ppid].gid;
1740143   proc_table[pid].egid = proc_table[ppid].egid;
1740144   proc_table[pid].sgid = proc_table[ppid].sgid;
1740145   proc_table[pid].device_tty = proc_table[ppid].device_tty;
1740146   proc_table[pid].sig_status = 0;
1740147   proc_table[pid].sig_ignore = 0;
1740148   // 
1740149   for (sig = 0; sig < MAX_SIGNALS; sig++)
1740150     {
1740151       proc_table[pid].sig_handler[sig]
1740152         = proc_table[ppid].sig_handler[sig];
1740153     }
1740154   // 
1740155   proc_table[pid].usage = 0;
1740156   proc_table[pid].status = PROC_CREATED;
1740157   proc_table[pid].wakeup_events = 0;
1740158   proc_table[pid].wakeup_signal = 0;
1740159   proc_table[pid].wakeup_timer = 0;
1740160   // 
1740161   if (proc_table[ppid].domain_data != 0)
1740162     {
1740163       proc_table[pid].address_text =
1740164         proc_table[ppid].address_text;
1740165     }
1740166   else
1740167     {
1740168       proc_table[pid].address_text = allocated_text;
1740169     }
1740170   proc_table[pid].domain_text =
1740171     proc_table[ppid].domain_text;
1740172   proc_table[pid].address_data = allocated_data;
1740173   proc_table[pid].domain_data =
1740174     proc_table[ppid].domain_data;
1740175   proc_table[pid].domain_stack =
1740176     proc_table[ppid].domain_stack;
1740177   proc_table[pid].extra_data = proc_table[ppid].extra_data;
1740178   proc_table[pid].sp = proc_stack_pointer;
1740179   proc_table[pid].ret = 0;
1740180   proc_table[pid].inode_cwd = proc_table[ppid].inode_cwd;
1740181   proc_table[pid].umask = proc_table[ppid].umask;
1740182   strncpy (proc_table[pid].name, proc_table[ppid].name,
1740183            PATH_MAX);
1740184   strncpy (proc_table[pid].path_cwd,
1740185            proc_table[ppid].path_cwd, PATH_MAX);
1740186   // 
1740187   // Update process TEXT segment inside the GDT table.
1740188   // 
1740189   gdt_segment (gdt_pid_to_segment_text (pid),
1740190                (uint32_t) proc_table[pid].address_text,
1740191                (uint32_t) (proc_table[pid].domain_text /
1740192                            4096), 1, 1, 0);
1740193   // 
1740194   // Update process DATA segment inside the GDT table.
1740195   // 
1740196   if (proc_table[pid].domain_data > 0)
1740197     {
1740198       gdt_segment (gdt_pid_to_segment_data (pid),
1740199                    (uint32_t) proc_table[pid].address_data,
1740200                    (uint32_t) ((proc_table[pid].domain_data
1740201                                 +
1740202                                 proc_table[pid].extra_data)
1740203                                / 4096), 1, 0, 0);
1740204     }
1740205   else
1740206     {
1740207       gdt_segment (gdt_pid_to_segment_data (pid),
1740208                    (uint32_t) proc_table[pid].address_text,
1740209                    (uint32_t) ((proc_table[pid].domain_text
1740210                                 +
1740211                                 proc_table[pid].extra_data)
1740212                                / 4096), 1, 0, 0);
1740213     }
1740214   // 
1740215   // -------------------------------------------------
1740216   // Might reload the GDT table, but it is not
1740217   // necessarily.
1740218   // Anyway, if you do it, nothing change. :-)
1740219   // 
1740220   // gdt_load (&gdt_register);
1740221   // -------------------------------------------------
1740222   // 
1740223   // Increase inode references for the working
1740224   // directory.
1740225   // 
1740226   proc_table[pid].inode_cwd->references++;
1740227   // 
1740228   // Duplicate valid file descriptors.
1740229   // 
1740230   for (fdn = 0; fdn < OPEN_MAX; fdn++)
1740231     {
1740232       if (proc_table[ppid].fd[fdn].file != NULL
1740233           && (proc_table[ppid].fd[fdn].file->inode !=
1740234               NULL
1740235               || proc_table[ppid].fd[fdn].file->sock !=
1740236               NULL))
1740237         {
1740238           // 
1740239           // Copy to the forked process.
1740240           // 
1740241           proc_table[pid].fd[fdn].fl_flags
1740242             = proc_table[ppid].fd[fdn].fl_flags;
1740243           proc_table[pid].fd[fdn].fd_flags
1740244             = proc_table[ppid].fd[fdn].fd_flags;
1740245           proc_table[pid].fd[fdn].file =
1740246             proc_table[ppid].fd[fdn].file;
1740247           // 
1740248           // Increment file reference.
1740249           // 
1740250           proc_table[ppid].fd[fdn].file->references++;
1740251           // 
1740252           // Check if it is a pipe and increment
1740253           // specific
1740254           // read/write reference counters inside the
1740255           // inode.
1740256           // 
1740257           if (proc_table[ppid].fd[fdn].file->inode !=
1740258               NULL
1740259               && S_ISFIFO (proc_table[ppid].fd[fdn].
1740260                            file->inode->mode))
1740261             {
1740262               if (proc_table[ppid].fd[fdn].
1740263                   fl_flags & O_RDONLY)
1740264                 {
1740265                   proc_table[ppid].fd[fdn].file->
1740266                     inode->pipe_ref_read++;
1740267                 }
1740268               // 
1740269               if (proc_table[ppid].fd[fdn].
1740270                   fl_flags & O_WRONLY)
1740271                 {
1740272                   proc_table[ppid].fd[fdn].file->
1740273                     inode->pipe_ref_write++;
1740274                 }
1740275             }
1740276         }
1740277     }
1740278   // 
1740279   // Change segment descriptor values inside the
1740280   // stack,
1740281   // for: DS==ES==FS==GS.
1740282   // 
1740283   // First calculate the absolute stack section
1740284   // address, from the
1740285   // kernel point of view.
1740286   // 
1740287   if (allocated_data > 0)
1740288     {
1740289       addr_stack_pointer = allocated_data;
1740290     }
1740291   else
1740292     {
1740293       addr_stack_pointer = allocated_text;
1740294     }
1740295   // 
1740296   // Then calculate the effective new stack pointer.
1740297   // 
1740298   addr_stack_pointer += proc_table[pid].sp;
1740299   // 
1740300   // Then calculate the segment descriptor, to be
1740301   // written
1740302   // inside the new process stack.
1740303   // 
1740304   segment_descriptor = (gdt_pid_to_segment_data (pid) * 8);
1740305   // 
1740306   // Then copy inside the stack the new values for
1740307   // data segments.
1740308   // 
1740309   dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE,
1740310           (addr_stack_pointer + 28),
1740311           &segment_descriptor,
1740312           (sizeof segment_descriptor), NULL);
1740313   dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE,
1740314           (addr_stack_pointer + 32),
1740315           &segment_descriptor,
1740316           (sizeof segment_descriptor), NULL);
1740317   dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE,
1740318           (addr_stack_pointer + 36),
1740319           &segment_descriptor,
1740320           (sizeof segment_descriptor), NULL);
1740321   dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE,
1740322           (addr_stack_pointer + 40),
1740323           &segment_descriptor,
1740324           (sizeof segment_descriptor), NULL);
1740325   // 
1740326   // Change segment descriptor value inside the stack
1740327   // for CS,
1740328   // if so is necessary.
1740329   // 
1740330   segment_descriptor = (gdt_pid_to_segment_text (pid) * 8);
1740331   // 
1740332   dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE,
1740333           (addr_stack_pointer + 48),
1740334           &segment_descriptor,
1740335           (sizeof segment_descriptor), NULL);
1740336   // 
1740337   // Set it ready.
1740338   // 
1740339   proc_table[pid].status = PROC_READY;
1740340   // 
1740341   // Return the new PID.
1740342   // 
1740343   return (pid);
1740344 }

94.8.17   kernel/lib_s/s_fstat.c

Si veda la sezione 87.55.

1750001 #include <kernel/proc.h>
1750002 #include <kernel/lib_s.h>
1750003 #include <errno.h>
1750004 #include <fcntl.h>
1750005 //----------------------------------------------------------
1750006 int
1750007 s_fstat (pid_t pid, int fdn, struct stat *buffer)
1750008 {
1750009   proc_t *ps;
1750010   inode_t *inode;
1750011   // 
1750012   // Get process.
1750013   // 
1750014   ps = proc_reference (pid);
1750015   // 
1750016   // Verify if the file descriptor is valid.
1750017   // 
1750018   if (ps->fd[fdn].file == NULL)
1750019     {
1750020       errset (EBADF);   // Bad file descriptor.
1750021       return (-1);
1750022     }
1750023   // 
1750024   // Reach the inode.
1750025   // 
1750026   inode = ps->fd[fdn].file->inode;
1750027   // 
1750028   // If the Inode does not exist, exit with error.
1750029   // 
1750030   if (inode == NULL)
1750031     {
1750032       errset (ENOENT);
1750033       return (-1);
1750034     }
1750035   // 
1750036   // Inode loaded: update the buffer.
1750037   // 
1750038   buffer->st_dev = inode->sb->device;
1750039   buffer->st_ino = inode->ino;
1750040   buffer->st_mode = inode->mode;
1750041   buffer->st_nlink = inode->links;
1750042   buffer->st_uid = inode->uid;
1750043   buffer->st_gid = inode->gid;
1750044   if (S_ISBLK (buffer->st_mode)
1750045       || S_ISCHR (buffer->st_mode))
1750046     {
1750047       buffer->st_rdev = inode->direct[0];
1750048     }
1750049   else
1750050     {
1750051       buffer->st_rdev = 0;
1750052     }
1750053   buffer->st_size = inode->size;
1750054   buffer->st_atime = inode->time;       // All times
1750055   // are the
1750056   // same for
1750057   buffer->st_mtime = inode->time;       // Minix 1
1750058   // file
1750059   // system.
1750060   buffer->st_ctime = inode->time;       // 
1750061   buffer->st_blksize = inode->sb->blksize;
1750062   buffer->st_blocks = inode->blkcnt;
1750063   // 
1750064   // If the inode is a device special file, the
1750065   // `st_rdev' value is
1750066   // taken from the first direct zone (as of Minix 1
1750067   // organization).
1750068   // 
1750069   if (S_ISBLK (inode->mode) || S_ISCHR (inode->mode))
1750070     {
1750071       buffer->st_rdev = inode->direct[0];
1750072     }
1750073   else
1750074     {
1750075       buffer->st_rdev = 0;
1750076     }
1750077   // 
1750078   // Return.
1750079   // 
1750080   return (0);
1750081 }

94.8.18   kernel/lib_s/s_ipconfig.c

Si veda la sezione 87.28.

1760001 #include <kernel/net.h>
1760002 #include <kernel/net/route.h>
1760003 #include <kernel/net/arp.h>
1760004 #include <errno.h>
1760005 #include <kernel/proc.h>
1760006 //----------------------------------------------------------
1760007 // This syscall is present only inside os32.
1760008 //----------------------------------------------------------
1760009 int
1760010 s_ipconfig (pid_t pid, int n, in_addr_t addr, int m)
1760011 {
1760012   // 
1760013   // Must be a privileged process.
1760014   // 
1760015   if (proc_table[pid].euid != 0)
1760016     {
1760017       errset (EPERM);
1760018       return (-1);
1760019     }
1760020   // 
1760021   // Check arguments: net0 cannot be modified, because 
1760022   // it is necessarily
1760023   // assigned to the loopback virtual interface.
1760024   // 
1760025   if (n > NET_MAX_DEVICES || n < 1)
1760026     {
1760027       errset (EINVAL);
1760028       return (-1);
1760029     }
1760030   if (m > 32 || n < 0)
1760031     {
1760032       errset (EINVAL);
1760033       return (-1);
1760034     }
1760035   // 
1760036   // Verify that the interface is present.
1760037   // 
1760038   if (net_table[n].type == NET_DEV_NULL)
1760039     {
1760040       errset (ENODEV);
1760041       return (-1);
1760042     }
1760043   // 
1760044   // Remove previous route related to the interface,
1760045   // if the interface
1760046   // was already configured.
1760047   // 
1760048   if (net_table[n].ip != 0 && net_table[n].m != 0)
1760049     {
1760050       s_routedel (pid, net_table[n].ip, net_table[n].m);
1760051     }
1760052   // 
1760053   // Modify the net_table[].
1760054   // 
1760055   net_table[n].ip = ntohl (addr);
1760056   net_table[n].m = m;
1760057   // 
1760058   // Add the route.
1760059   // 
1760060   if (net_table[n].ip != 0 && net_table[n].m != 0)
1760061     {
1760062       return (s_routeadd (pid, addr, m, 0, n));
1760063     }
1760064   // 
1760065   return (0);
1760066 }

94.8.19   kernel/lib_s/s_kill.c

Si veda la sezione 87.29.

1770001 #include <kernel/proc.h>
1770002 #include <kernel/lib_s.h>
1770003 #include <errno.h>
1770004 //----------------------------------------------------------
1770005 int
1770006 s_kill (pid_t pid_killer, pid_t pid_target, int sig)
1770007 {
1770008   uid_t euid = proc_table[pid_killer].euid;
1770009   uid_t uid = proc_table[pid_killer].uid;
1770010   pid_t pgrp = proc_table[pid_killer].pgrp;
1770011   int p;        // Index inside the process table.
1770012   // 
1770013   if (pid_target < -1)
1770014     {
1770015       errset (ESRCH);
1770016       return (-1);
1770017     }
1770018   else if (pid_target == -1)
1770019     {
1770020       if (sig == 0)
1770021         {
1770022           return (0);
1770023         }
1770024       if (euid == 0)
1770025         {
1770026           // 
1770027           // Because `pid_target' is qual to `-1' and
1770028           // the effective
1770029           // user identity is `0', then, all
1770030           // processes,
1770031           // except the kernel and init, will receive
1770032           // the signal.
1770033           // 
1770034           // The following scan starts from 2, to
1770035           // preserve the
1770036           // kernel and init processes.
1770037           // 
1770038           for (p = 2; p < PROCESS_MAX; p++)
1770039             {
1770040               if (proc_table[p].status != PROC_EMPTY
1770041                   && proc_table[p].status != PROC_ZOMBIE)
1770042                 {
1770043                   proc_sig_on (p, sig);
1770044                 }
1770045             }
1770046         }
1770047       else
1770048         {
1770049           // 
1770050           // Because `pid_target' is qual to `-1', but 
1770051           // the effective
1770052           // user identity is not `0', then, all
1770053           // processes owned
1770054           // by the same effective user identity, will 
1770055           // receive the
1770056           // signal.
1770057           // 
1770058           // The following scan starts from 1, to
1770059           // preserve the
1770060           // kernel process.
1770061           // 
1770062           for (p = 1; p < PROCESS_MAX; p++)
1770063             {
1770064               if (proc_table[p].status != PROC_EMPTY
1770065                   && proc_table[p].status !=
1770066                   PROC_ZOMBIE && proc_table[p].uid == euid)
1770067                 {
1770068                   proc_sig_on (p, sig);
1770069                 }
1770070             }
1770071         }
1770072       return (0);
1770073     }
1770074   else if (pid_target == 0)
1770075     {
1770076       if (sig == 0)
1770077         {
1770078           return (0);
1770079         }
1770080       // 
1770081       // The following scan starts from 1, to preserve 
1770082       // the
1770083       // kernel process.
1770084       // 
1770085       for (p = 1; p < PROCESS_MAX; p++)
1770086         {
1770087           if (proc_table[p].status != PROC_EMPTY
1770088               && proc_table[p].status != PROC_ZOMBIE
1770089               && proc_table[p].pgrp == pgrp)
1770090             {
1770091               proc_sig_on (p, sig);
1770092             }
1770093         }
1770094       return (0);
1770095     }
1770096   else if (pid_target >= PROCESS_MAX)
1770097     {
1770098       errset (ESRCH);
1770099       return (-1);
1770100     }
1770101   else  // (pid_target > 0)
1770102     {
1770103       if (proc_table[pid_target].status == PROC_EMPTY
1770104           || proc_table[pid_target].status == PROC_ZOMBIE)
1770105         {
1770106           errset (ESRCH);
1770107           return (-1);
1770108         }
1770109       else if (uid == proc_table[pid_target].uid ||
1770110                uid == proc_table[pid_target].suid ||
1770111                euid == proc_table[pid_target].uid ||
1770112                euid == proc_table[pid_target].suid
1770113                || euid == 0)
1770114         {
1770115           if (sig == 0)
1770116             {
1770117               return (0);
1770118             }
1770119           else
1770120             {
1770121               proc_sig_on (pid_target, sig);
1770122               return (0);
1770123             }
1770124         }
1770125       else
1770126         {
1770127           errset (EPERM);
1770128           return (-1);
1770129         }
1770130     }
1770131 }

94.8.20   kernel/lib_s/s_link.c

Si veda la sezione 87.30.

1780001 #include <kernel/fs.h>
1780002 #include <errno.h>
1780003 #include <kernel/proc.h>
1780004 #include <kernel/lib_s.h>
1780005 //----------------------------------------------------------
1780006 int
1780007 s_link (pid_t pid, const char *path_old,
1780008         const char *path_new)
1780009 {
1780010   proc_t *ps;
1780011   inode_t *inode_old;
1780012   inode_t *inode_new;
1780013   char path_new_full[PATH_MAX];
1780014   // 
1780015   // Get process.
1780016   // 
1780017   ps = proc_reference (pid);
1780018   // 
1780019   // Try to get the old path inode.
1780020   // 
1780021   inode_old = path_inode (pid, path_old);
1780022   if (inode_old == NULL)
1780023     {
1780024       // 
1780025       // Cannot get the inode: `errno' is already set
1780026       // by
1780027       // `path_inode()'.
1780028       // 
1780029       errset (errno);
1780030       return (-1);
1780031     }
1780032   // 
1780033   // The inode is available and checks are done:
1780034   // arrange to get a
1780035   // packed full path name and then the destination
1780036   // directory path.
1780037   // 
1780038   path_full (path_new, ps->path_cwd, path_new_full);
1780039   // 
1780040   // 
1780041   // 
1780042   inode_new =
1780043     path_inode_link (pid, path_new_full, inode_old,
1780044                      (mode_t) 0);
1780045   if (inode_new == NULL)
1780046     {
1780047       inode_put (inode_old);
1780048       return (-1);
1780049     }
1780050   if (inode_new != inode_old)
1780051     {
1780052       inode_put (inode_new);
1780053       inode_put (inode_old);
1780054       errset (EUNKNOWN);        // Unknown error.
1780055       return (-1);
1780056     }
1780057   // 
1780058   // Inode data is already updated by
1780059   // `path_inode_link()': just put
1780060   // it and return. Please note that only one is put,
1780061   // because it is
1780062   // just the same of the other.
1780063   // 
1780064   inode_put (inode_new);
1780065   return (0);
1780066 }

94.8.21   kernel/lib_s/s_listen.c

Si veda la sezione 87.31.

1790001 #include <kernel/proc.h>
1790002 #include <kernel/lib_s.h>
1790003 #include <kernel/lib_k.h>
1790004 #include <errno.h>
1790005 #include <fcntl.h>
1790006 #include <sys/socket.h>
1790007 #include <arpa/inet.h>
1790008 //----------------------------------------------------------
1790009 int
1790010 s_listen (pid_t pid, int sfdn, int backlog)
1790011 {
1790012   fd_t *sfd;
1790013   int s;
1790014   // 
1790015   // Get file descriptor and verify that it is a
1790016   // socket.
1790017   // 
1790018   sfd = fd_reference (pid, &sfdn);
1790019   if (sfd == NULL || sfd->file == NULL)
1790020     {
1790021       errset (EBADF);   // Bad file descriptor.
1790022       return (-1);
1790023     }
1790024   if (sfd->file->sock == NULL)
1790025     {
1790026       errset (ENOTSOCK);        // Not a socket.
1790027       return (-1);
1790028     }
1790029   if (sfd->file->sock->type != SOCK_STREAM)
1790030     {
1790031       errset (EOPNOTSUPP);      // Not a stream
1790032       // socket.
1790033       return (-1);
1790034     }
1790035   if (sfd->file->sock->raddr != 0
1790036       || sfd->file->sock->rport != 0)
1790037     {
1790038       // 
1790039       // The socket is connected, and cannot be good
1790040       // for
1790041       // listening.
1790042       // 
1790043       errset (EISCONN);
1790044       return (-1);
1790045     }
1790046   // 
1790047   // Scan the other sockets to find if there is
1790048   // another one listening.
1790049   // 
1790050   for (s = 0; s < SOCK_MAX_SLOTS; s++)
1790051     {
1790052       if (sock_table[s].tcp.conn == TCP_LISTEN
1790053           && sock_table[s].lport == sfd->file->sock->lport)
1790054         {
1790055           // 
1790056           // Yes, there is one: sorry.
1790057           // 
1790058           errset (EADDRINUSE);
1790059           return (-1);
1790060         }
1790061     }
1790062   // 
1790063   // Check the current TCP state.
1790064   // 
1790065   if (sfd->file->sock->tcp.conn != 0
1790066       && sfd->file->sock->tcp.conn != TCP_LISTEN)
1790067     {
1790068       // 
1790069       // Cannot change the socket stream state.
1790070       // 
1790071       errset (EISCONN);
1790072       return (-1);
1790073     }
1790074   // 
1790075   // The socket might be already listening, but the
1790076   // newly requested
1790077   // queue should be greater or equal to the previous
1790078   // one.
1790079   // 
1790080   if (sfd->file->sock->tcp.conn == TCP_LISTEN
1790081       && backlog < sfd->file->sock->tcp.listen_max)
1790082     {
1790083       // 
1790084       // Cannot reduce the listen queue: just ignore.
1790085       // 
1790086       return (0);
1790087     }
1790088   // 
1790089   // Ok.
1790090   // 
1790091   sfd->file->sock->tcp.conn = TCP_LISTEN;
1790092   sfd->file->sock->tcp.listen_max =
1790093     min (backlog, SOCK_MAX_QUEUE);
1790094   sfd->file->sock->tcp.listen_pid = pid;
1790095   return (0);
1790096 }

94.8.22   kernel/lib_s/s_longjmp.c

Si veda la sezione 87.49.

1800001 #include <kernel/lib_s.h>
1800002 #include <kernel/proc.h>
1800003 #include <errno.h>
1800004 #include <sys/os32.h>
1800005 //----------------------------------------------------------
1800006 extern uint32_t proc_stack_pointer;
1800007 //----------------------------------------------------------
1800008 void
1800009 s_longjmp (pid_t pid, jmp_buf env, int val)
1800010 {
1800011   jmp_stack_t *sp;
1800012   jmp_env_t *jmpenv;
1800013   // 
1800014   // Translate the pointer `env', to the kernel point
1800015   // of view.
1800016   // 
1800017   jmpenv = ptr (pid, env);
1800018   // 
1800019   // Find where *was* the process stack in memory,
1800020   // from the kernel point
1800021   // of view. Please notice that the current stack at
1800022   // `proc_stack_pointer' will be saved from the
1800023   // scheduler inside
1800024   // the process table. So, the replacement is made at 
1800025   // the current
1800026   // stack position, and not inside the process table.
1800027   // 
1800028   sp = ptr (pid, (void *) jmpenv->esp0);
1800029   // 
1800030   // Restore the process stack.
1800031   // 
1800032   sp->eax0 = jmpenv->eax0;
1800033   sp->ecx0 = jmpenv->ecx0;
1800034   sp->edx0 = jmpenv->edx0;
1800035   sp->ebx0 = jmpenv->ebx0;
1800036   sp->ebp0 = jmpenv->ebp0;
1800037   sp->esi0 = jmpenv->esi0;
1800038   sp->edi0 = jmpenv->edi0;
1800039   sp->ds0 = jmpenv->ds0;
1800040   sp->es0 = jmpenv->es0;
1800041   sp->fs0 = jmpenv->fs0;
1800042   sp->gs0 = jmpenv->gs0;
1800043   sp->eflags0 = jmpenv->eflags0;
1800044   sp->cs0 = jmpenv->cs0;
1800045   sp->eip0 = jmpenv->eip0;
1800046   // 
1800047   sp->eip1 = jmpenv->eip1;
1800048   sp->syscallnr = jmpenv->syscallnr;
1800049   sp->msg_pointer = jmpenv->msg_pointer;
1800050   sp->msg_size = jmpenv->msg_size;
1800051   sp->env = jmpenv->env;
1800052   sp->ret = val;
1800053   sp->ebp1 = jmpenv->ebp1;
1800054   sp->eip2 = jmpenv->eip2;
1800055   // 
1800056   // Replace the stack pointer too!
1800057   // 
1800058   proc_stack_pointer = jmpenv->esp0;
1800059 }

94.8.23   kernel/lib_s/s_lseek.c

Si veda la sezione 87.33.

1810001 #include <kernel/proc.h>
1810002 #include <kernel/lib_s.h>
1810003 #include <errno.h>
1810004 //----------------------------------------------------------
1810005 off_t
1810006 s_lseek (pid_t pid, int fdn, off_t offset, int whence)
1810007 {
1810008   inode_t *inode;
1810009   file_t *file;
1810010   fd_t *fd;
1810011   off_t test_offset;
1810012   // 
1810013   // Get file descriptor.
1810014   // 
1810015   fd = fd_reference (pid, &fdn);
1810016   if (fd == NULL || fd->file == NULL
1810017       || fd->file->inode == NULL)
1810018     {
1810019       errset (EBADF);   // Bad file descriptor.
1810020       return (-1);
1810021     }
1810022   // 
1810023   // Get file table item.
1810024   // 
1810025   file = fd->file;
1810026   // 
1810027   // Get inode.
1810028   // 
1810029   inode = file->inode;
1810030   // 
1810031   // Change position depending on the `whence'
1810032   // parameter.
1810033   // 
1810034   if (whence == SEEK_SET)
1810035     {
1810036       if (offset < 0)
1810037         {
1810038           errset (EINVAL);      // Invalid argument.
1810039           return ((off_t) - 1);
1810040         }
1810041       else
1810042         {
1810043           fd->file->offset = offset;
1810044         }
1810045     }
1810046   else if (whence == SEEK_CUR)
1810047     {
1810048       test_offset = fd->file->offset;
1810049       test_offset += offset;
1810050       if (test_offset < 0)
1810051         {
1810052           errset (EINVAL);      // Invalid argument.
1810053           return ((off_t) - 1);
1810054         }
1810055       else
1810056         {
1810057           fd->file->offset = test_offset;
1810058         }
1810059     }
1810060   else if (whence == SEEK_END)
1810061     {
1810062       test_offset = inode->size;
1810063       test_offset += offset;
1810064       if (test_offset < 0)
1810065         {
1810066           errset (EINVAL);      // Invalid argument.
1810067           return ((off_t) - 1);
1810068         }
1810069       else
1810070         {
1810071           fd->file->offset = test_offset;
1810072         }
1810073     }
1810074   else
1810075     {
1810076       errset (EINVAL);  // Invalid argument.
1810077       return ((off_t) - 1);
1810078     }
1810079   // 
1810080   // Return the new file position.
1810081   // 
1810082   return (fd->file->offset);
1810083 }

94.8.24   kernel/lib_s/s_mkdir.c

Si veda la sezione 87.34.

1820001 #include <kernel/fs.h>
1820002 #include <errno.h>
1820003 #include <kernel/proc.h>
1820004 #include <libgen.h>
1820005 #include <kernel/lib_s.h>
1820006 //----------------------------------------------------------
1820007 int
1820008 s_mkdir (pid_t pid, const char *path, mode_t mode)
1820009 {
1820010   proc_t *ps;
1820011   inode_t *inode_directory;
1820012   inode_t *inode_parent;
1820013   int status;
1820014   char path_directory[PATH_MAX];
1820015   char path_copy[PATH_MAX];
1820016   char *path_parent;
1820017   ssize_t size_written;
1820018   // 
1820019   struct
1820020   {
1820021     ino_t ino_1;
1820022     char name_1[NAME_MAX];
1820023     ino_t ino_2;
1820024     char name_2[NAME_MAX];
1820025   } directory;
1820026   // 
1820027   // Get process.
1820028   // 
1820029   ps = proc_reference (pid);
1820030   // 
1820031   // Correct the mode with the umask.
1820032   // 
1820033   mode &= ~ps->umask;
1820034   // 
1820035   // Inside `mode', the file type is fixed. No check
1820036   // is made.
1820037   // 
1820038   mode &= 00777;
1820039   mode |= S_IFDIR;
1820040   // 
1820041   // The full path and the directory path is needed.
1820042   // 
1820043   status = path_full (path, ps->path_cwd, path_directory);
1820044   if (status < 0)
1820045     {
1820046       return (-1);
1820047     }
1820048   strncpy (path_copy, path_directory, PATH_MAX);
1820049   path_copy[PATH_MAX - 1] = 0;
1820050   path_parent = dirname (path_copy);
1820051   // 
1820052   // Check if something already exists with the same
1820053   // name. The scan
1820054   // is done with kernel privileges.
1820055   // 
1820056   inode_directory = path_inode ((uid_t) 0, path_directory);
1820057   if (inode_directory != NULL)
1820058     {
1820059       // 
1820060       // The file already exists. Put inode and return 
1820061       // an error.
1820062       // 
1820063       inode_put (inode_directory);
1820064       errset (EEXIST);  // File exists.
1820065       return (-1);
1820066     }
1820067   // 
1820068   // Try to locate the directory that should contain
1820069   // this one.
1820070   // 
1820071   inode_parent = path_inode (pid, path_parent);
1820072   if (inode_parent == NULL)
1820073     {
1820074       // 
1820075       // Cannot locate the directory: return an error. 
1820076       // The variable
1820077       // `errno' should already be set by
1820078       // `path_inode()'.
1820079       // 
1820080       errset (errno);
1820081       return (-1);
1820082     }
1820083   // 
1820084   // Try to create the node: should fail if the user
1820085   // does not have
1820086   // enough permissions.
1820087   // 
1820088   inode_directory =
1820089     path_inode_link (pid, path_directory, NULL, mode);
1820090   if (inode_directory == NULL)
1820091     {
1820092       // 
1820093       // Sorry: cannot create the inode! The variable
1820094       // `errno' should
1820095       // already be set by `path_inode_link()'.
1820096       // 
1820097       errset (errno);
1820098       return (-1);
1820099     }
1820100   // 
1820101   // Fill records for `.' and `..'.
1820102   // 
1820103   directory.ino_1 = inode_directory->ino;
1820104   strncpy (directory.name_1, ".", (size_t) 3);
1820105   directory.ino_2 = inode_parent->ino;
1820106   strncpy (directory.name_2, "..", (size_t) 3);
1820107   // 
1820108   // Write data.
1820109   // 
1820110   size_written =
1820111     inode_file_write (inode_directory, (off_t) 0,
1820112                       &directory, (sizeof directory));
1820113   if (size_written != (sizeof directory))
1820114     {
1820115       return (-1);
1820116     }
1820117   // 
1820118   // Fix directory inode links.
1820119   // 
1820120   inode_directory->links = 2;
1820121   inode_directory->time = s_time (pid, NULL);
1820122   inode_directory->changed = 1;
1820123   // 
1820124   // Fix parent directory inode links.
1820125   // 
1820126   inode_parent->links++;
1820127   inode_parent->time = s_time (pid, NULL);
1820128   inode_parent->changed = 1;
1820129   // 
1820130   // Save and put the inodes.
1820131   // 
1820132   inode_save (inode_parent);
1820133   inode_save (inode_directory);
1820134   inode_put (inode_parent);
1820135   inode_put (inode_directory);
1820136   // 
1820137   // Return.
1820138   // 
1820139   return (0);
1820140 }

94.8.25   kernel/lib_s/s_mknod.c

Si veda la sezione 87.35.

1830001 #include <kernel/fs.h>
1830002 #include <errno.h>
1830003 #include <kernel/proc.h>
1830004 #include <kernel/lib_s.h>
1830005 //----------------------------------------------------------
1830006 int
1830007 s_mknod (pid_t pid, const char *path, mode_t mode,
1830008          dev_t device)
1830009 {
1830010   proc_t *ps;
1830011   inode_t *inode;
1830012   char full_path[PATH_MAX];
1830013   // 
1830014   // Get process.
1830015   // 
1830016   ps = proc_reference (pid);
1830017   // 
1830018   // Correct the mode with the umask.
1830019   // 
1830020   mode &= ~ps->umask;
1830021   // 
1830022   // Currently must be root, unless the type is a
1830023   // regular file,
1830024   // or a FIFO file.
1830025   // 
1830026   if (!(S_ISFIFO (mode) || S_ISREG (mode)))
1830027     {
1830028       if (ps->uid != 0)
1830029         {
1830030           errset (EPERM);       // Operation not
1830031           // permitted.
1830032           return (-1);
1830033         }
1830034     }
1830035   // 
1830036   // Check the type of node requested.
1830037   // 
1830038   if (!(S_ISBLK (mode) ||
1830039         S_ISCHR (mode) ||
1830040         S_ISREG (mode) || S_ISFIFO (mode)
1830041         || S_ISDIR (mode)))
1830042     {
1830043       errset (EINVAL);  // Invalid argument.
1830044       return (-1);
1830045     }
1830046   // 
1830047   // Check if something already exists with the same
1830048   // name.
1830049   // 
1830050   inode = path_inode (pid, path);
1830051   if (inode != NULL)
1830052     {
1830053       // 
1830054       // The file already exists. Put inode and return 
1830055       // an error.
1830056       // 
1830057       inode_put (inode);
1830058       errset (EEXIST);  // File exists.
1830059       return (-1);
1830060     }
1830061   // 
1830062   // Try to creat the node.
1830063   // 
1830064   path_full (path, ps->path_cwd, full_path);
1830065   inode = path_inode_link (pid, full_path, NULL, mode);
1830066   if (inode == NULL)
1830067     {
1830068       // 
1830069       // Sorry: cannot create the inode!
1830070       // 
1830071       return (-1);
1830072     }
1830073   // 
1830074   // Set the device number if necessary.
1830075   // 
1830076   if (S_ISBLK (mode) || S_ISCHR (mode))
1830077     {
1830078       inode->direct[0] = device;
1830079       inode->changed = 1;
1830080     }
1830081   // 
1830082   // Put the inode.
1830083   // 
1830084   inode_put (inode);
1830085   // 
1830086   // Return.
1830087   // 
1830088   return (0);
1830089 }

94.8.26   kernel/lib_s/s_mount.c

Si veda la sezione 87.36.

1840001 #include <kernel/fs.h>
1840002 #include <errno.h>
1840003 #include <kernel/proc.h>
1840004 #include <kernel/lib_s.h>
1840005 //----------------------------------------------------------
1840006 int
1840007 s_mount (pid_t pid, const char *path_dev,
1840008          const char *path_mnt, int options)
1840009 {
1840010   proc_t *ps;
1840011   dev_t device; // Device to mount.
1840012   inode_t *inode_mnt;   // Directory mount point.
1840013   void *pstatus;
1840014   // 
1840015   // Get process.
1840016   // 
1840017   ps = proc_reference (pid);
1840018   // 
1840019   // Verify to be the super user.
1840020   // 
1840021   if (ps->euid != 0)
1840022     {
1840023       errset (EPERM);   // Operation not permitted.
1840024       return (-1);
1840025     }
1840026   // 
1840027   device = path_device (pid, path_dev);
1840028   if (device < 0)
1840029     {
1840030       return (-1);
1840031     }
1840032   // 
1840033   inode_mnt = path_inode (pid, path_mnt);
1840034   if (inode_mnt == NULL)
1840035     {
1840036       return (-1);
1840037     }
1840038   if (!S_ISDIR (inode_mnt->mode))
1840039     {
1840040       inode_put (inode_mnt);
1840041       errset (ENOTDIR); // Not a directory.
1840042       return (-1);
1840043     }
1840044   if (inode_mnt->sb_attached != NULL)
1840045     {
1840046       inode_put (inode_mnt);
1840047       errset (EBUSY);   // Device or resource busy.
1840048       return (-1);
1840049     }
1840050   // 
1840051   // All data is available.
1840052   // 
1840053   pstatus = sb_mount (device, &inode_mnt, options);
1840054   if (pstatus == NULL)
1840055     {
1840056       inode_put (inode_mnt);
1840057       return (-1);
1840058     }
1840059   // 
1840060   return (0);
1840061 }

94.8.27   kernel/lib_s/s_open.c

Si veda la sezione 87.37.

1850001 #include <kernel/proc.h>
1850002 #include <kernel/lib_s.h>
1850003 #include <kernel/lib_k.h>
1850004 #include <errno.h>
1850005 #include <fcntl.h>
1850006 //----------------------------------------------------------
1850007 int
1850008 s_open (pid_t pid, const char *path, int oflags,
1850009         mode_t mode)
1850010 {
1850011   inode_t *inode;
1850012   int status;
1850013   file_t *file;
1850014   fd_t *fd;
1850015   int fdn;
1850016   char full_path[PATH_MAX];
1850017   int perm;
1850018   tty_t *tty;
1850019   mode_t umask;
1850020   int errno_save;
1850021   // 
1850022   // k_printf ("%s(%i, %s, %x, %05o)\n", __func__,
1850023   // (int) pid,
1850024   // path, oflags, (int) mode);
1850025   // 
1850026   // Check path argument.
1850027   // 
1850028   if (path == NULL || strlen (path) == 0)
1850029     {
1850030       errset (EINVAL);  // Invalid argument.
1850031       return (-1);
1850032     }
1850033   // 
1850034   // Correct the mode with the umask. As it is not a
1850035   // directory, to the
1850036   // mode are removed execution and sticky
1850037   // permissions.
1850038   // 
1850039   umask = proc_table[pid].umask | 01111;
1850040   mode &= ~umask;
1850041   // 
1850042   // Check open options.
1850043   // 
1850044   if (oflags & O_WRONLY)
1850045     {
1850046       // 
1850047       // The file is to be opened for write, or for
1850048       // read/write.
1850049       // Try to get inode.
1850050       // 
1850051       inode = path_inode (pid, path);
1850052       if (inode == NULL)
1850053         {
1850054           // 
1850055           // Cannot get the inode. See if there is the 
1850056           // creation
1850057           // option.
1850058           // 
1850059           if (oflags & O_CREAT)
1850060             {
1850061               // 
1850062               // Try to create the missing inode: the
1850063               // file must be a
1850064               // regular one, so add the mode.
1850065               // 
1850066               path_full (path,
1850067                          proc_table[pid].path_cwd,
1850068                          full_path);
1850069               inode =
1850070                 path_inode_link (pid, full_path, NULL,
1850071                                  (mode | S_IFREG));
1850072               if (inode == NULL)
1850073                 {
1850074                   // 
1850075                   // Sorry: cannot create the inode!
1850076                   // Variable `errno'
1850077                   // is already set by
1850078                   // `path_inode_link()'.
1850079                   // 
1850080                   errset (errno);
1850081                   return (-1);
1850082                 }
1850083             }
1850084           else
1850085             {
1850086               // 
1850087               // Cannot open the inode. Variable
1850088               // `errno'
1850089               // should be already set by
1850090               // `path_inode()'.
1850091               // 
1850092               errset (errno);
1850093               return (-1);
1850094             }
1850095         }
1850096       // 
1850097       // The inode was read or created: check if it
1850098       // must be
1850099       // truncated. It can be truncated only if it is
1850100       // a regular
1850101       // file.
1850102       // 
1850103       if (oflags & O_TRUNC && inode->mode & S_IFREG)
1850104         {
1850105           // 
1850106           // Truncate inode.
1850107           // 
1850108           status = inode_truncate (inode);
1850109           if (status != 0)
1850110             {
1850111               // 
1850112               // Cannot truncate the inode: release it 
1850113               // and return.
1850114               // But this error should never happen,
1850115               // because the
1850116               // function `inode_truncate()' will not
1850117               // return any
1850118               // other value than zero.
1850119               // 
1850120               errno_save = errno;
1850121               inode_put (inode);
1850122               errset (errno_save);
1850123               return (-1);
1850124             }
1850125         }
1850126     }
1850127   else
1850128     {
1850129       // 
1850130       // The file is to be opened for read, but not
1850131       // for write.
1850132       // Try to get inode.
1850133       // 
1850134       inode = path_inode (pid, path);
1850135       if (inode == NULL)
1850136         {
1850137           // 
1850138           // Cannot open the file.
1850139           // 
1850140           errset (errno);
1850141           return (-1);
1850142         }
1850143     }
1850144   // 
1850145   // An inode was opened: check type and access
1850146   // permissions.
1850147   // All file types are good, even directories, as the 
1850148   // type
1850149   // DIR is implemented through file descriptors.
1850150   // 
1850151   perm = 0;
1850152   if (oflags & O_RDONLY)
1850153     perm |= 4;
1850154   if (oflags & O_WRONLY)
1850155     perm |= 2;
1850156   status =
1850157     inode_check (inode, S_IFMT, perm,
1850158                  proc_table[pid].euid,
1850159                  proc_table[pid].egid);
1850160   if (status != 0)
1850161     {
1850162       // 
1850163       // The file type is not correct or the user does 
1850164       // not have
1850165       // permissions.
1850166       // 
1850167       return (-1);
1850168     }
1850169   // 
1850170   // Allocate the file, inside the file table.
1850171   // 
1850172   file = file_reference (-1);
1850173   if (file == NULL)
1850174     {
1850175       // 
1850176       // Cannot allocate the file inside the file
1850177       // table: release the
1850178       // inode, update `errno' and return.
1850179       // 
1850180       inode_put (inode);
1850181       errset (ENFILE);  // Too many files open in
1850182       // system.
1850183       return (-1);
1850184     }
1850185   // 
1850186   // Put some data inside the file item. Only options
1850187   // O_RDONLY and O_WRONLY are kept here, because the
1850188   // O_APPEND
1850189   // is saved inside the file descriptor table.
1850190   // 
1850191   file->references = 1;
1850192   file->oflags = (oflags & (O_RDONLY | O_WRONLY));
1850193   file->inode = inode;
1850194   file->sock = NULL;
1850195   // 
1850196   // Allocate the file descriptor: variable `fdn' will 
1850197   // be modified
1850198   // by the call to `fd_reference()'.
1850199   // 
1850200   fdn = -1;
1850201   fd = fd_reference (pid, &fdn);
1850202   if (fd == NULL)
1850203     {
1850204       // 
1850205       // Cannot allocate the file descriptor: remove
1850206       // the item from
1850207       // file table.
1850208       // 
1850209       file->references = 0;
1850210       file->oflags = 0;
1850211       file->inode = NULL;
1850212       file->sock = NULL;
1850213       // 
1850214       // Release the inode.
1850215       // 
1850216       inode_put (inode);
1850217       // 
1850218       // Return an error.
1850219       // 
1850220       errset (EMFILE);  // Too many open files.
1850221       return (-1);
1850222     }
1850223   // 
1850224   // File descriptor allocated: put some data inside
1850225   // the
1850226   // file descriptor item.
1850227   // 
1850228   fd->fl_flags =
1850229     (oflags & (O_RDONLY | O_WRONLY | O_APPEND));
1850230   fd->fd_flags = 0;
1850231   fd->file = file;
1850232   fd->file->offset = 0;
1850233   // 
1850234   // Check for particular types and situations.
1850235   // 
1850236   if ((S_ISCHR (inode->mode))
1850237       && (oflags & O_RDONLY) && (oflags & O_WRONLY))
1850238     {
1850239       // 
1850240       // The inode is a character special file
1850241       // (related to a character
1850242       // device), opened for read and write!
1850243       // 
1850244       if ((inode->direct[0] & 0xFF00) ==
1850245           (DEV_CONSOLE_MAJOR << 8))
1850246         {
1850247           // 
1850248           // It is a terminal (currently only consoles 
1850249           // are possible).
1850250           // Get the tty reference.
1850251           // 
1850252           tty = tty_reference ((dev_t) inode->direct[0]);
1850253           // 
1850254           // Verify that the terminal is not already
1850255           // the controlling
1850256           // terminal of some process group.
1850257           // 
1850258           if (tty->pgrp == 0)
1850259             {
1850260               // 
1850261               // The terminal is free: verify if the
1850262               // current process
1850263               // needs a controlling terminal.
1850264               // 
1850265               if (proc_table[pid].device_tty == 0
1850266                   && proc_table[pid].pgrp == pid)
1850267                 {
1850268                   // 
1850269                   // It is a group leader with no
1850270                   // controlling
1850271                   // terminal: set the controlling
1850272                   // terminal.
1850273                   // 
1850274                   proc_table[pid].device_tty =
1850275                     inode->direct[0];
1850276                   tty->pgrp = proc_table[pid].pgrp;
1850277                 }
1850278             }
1850279         }
1850280     }
1850281   else if (S_ISFIFO (inode->mode))
1850282     {
1850283       // 
1850284       // It is FIFO (named pipe).
1850285       // 
1850286       if ((oflags & O_ACCMODE) == O_RDWR)
1850287         {
1850288           inode->pipe_ref_read++;
1850289           inode->pipe_ref_write++;
1850290         }
1850291       else if (oflags & O_RDONLY)
1850292         {
1850293           inode->pipe_ref_read++;
1850294           // 
1850295           // Go to sleep if there are no processes
1850296           // writing to the
1850297           // inode. Otherwise, wake them up.
1850298           // 
1850299           if (inode->pipe_ref_write == 0)
1850300             {
1850301               proc_table[pid].status = PROC_SLEEPING;
1850302               proc_table[pid].ret = 0;
1850303               proc_table[pid].wakeup_inode = inode;
1850304               proc_table[pid].wakeup_events =
1850305                 WAKEUP_EVENT_PIPE_READ;
1850306             }
1850307           else
1850308             {
1850309               proc_wakeup_pipe_write (inode);
1850310             }
1850311         }
1850312       else if (oflags & O_WRONLY)
1850313         {
1850314           inode->pipe_ref_write++;
1850315           // 
1850316           // Go to sleep if there are no processes
1850317           // reading to the
1850318           // inode. Otherwise, wake them up.
1850319           // 
1850320           if (inode->pipe_ref_read == 0)
1850321             {
1850322               proc_table[pid].status = PROC_SLEEPING;
1850323               proc_table[pid].ret = 0;
1850324               proc_table[pid].wakeup_inode = inode;
1850325               proc_table[pid].wakeup_events =
1850326                 WAKEUP_EVENT_PIPE_WRITE;
1850327             }
1850328           else
1850329             {
1850330               proc_wakeup_pipe_read (inode);
1850331             }
1850332         }
1850333     }
1850334   // 
1850335   // Return the file descriptor.
1850336   // 
1850337   return (fdn);
1850338 }

94.8.28   kernel/lib_s/s_pipe.c

Si veda la sezione 87.38.

1860001 #include <kernel/proc.h>
1860002 #include <kernel/lib_s.h>
1860003 #include <kernel/lib_k.h>
1860004 #include <errno.h>
1860005 #include <fcntl.h>
1860006 //----------------------------------------------------------
1860007 int
1860008 s_pipe (pid_t pid, int pipefd[2])
1860009 {
1860010   file_t *file;
1860011   fd_t *fd_read;
1860012   fd_t *fd_write;
1860013   int fdn_read;
1860014   int fdn_write;
1860015   // 
1860016   // Allocate the file inside the file table and the
1860017   // inode inside
1860018   // the inode table.
1860019   // 
1860020   file = file_pipe_make ();
1860021   if (file == NULL)
1860022     {
1860023       errset (errno);
1860024       return (-1);
1860025     }
1860026   // 
1860027   // Prepare file descriptor for read.
1860028   // 
1860029   fdn_read = -1;
1860030   fd_read = fd_reference (pid, &fdn_read);
1860031   if (fd_read == NULL)
1860032     {
1860033       // 
1860034       // Cannot allocate the file descriptor: remove
1860035       // the item from
1860036       // file table and put the relative inode.
1860037       // 
1860038       file->references = 0;
1860039       file->oflags = 0;
1860040       inode_put (file->inode);
1860041       file->inode = NULL;
1860042       // 
1860043       // Return an error.
1860044       // 
1860045       errset (EMFILE);  // Too many open files.
1860046       return (-1);
1860047     }
1860048   // 
1860049   // File descriptor allocated: put some data inside
1860050   // the
1860051   // file descriptor item and increment the pipe
1860052   // references
1860053   // for read.
1860054   // 
1860055   fd_read->fl_flags = O_RDONLY;
1860056   fd_read->fd_flags = 0;
1860057   fd_read->file = file;
1860058   fd_read->file->offset = 0;
1860059   fd_read->file->inode->pipe_ref_read++;
1860060   // 
1860061   // Prepare file descriptor for write.
1860062   // 
1860063   fdn_write = -1;
1860064   fd_write = fd_reference (pid, &fdn_write);
1860065   if (fd_write == NULL)
1860066     {
1860067       // 
1860068       // Cannot allocate the file descriptor: remove
1860069       // the item from
1860070       // file table and put the relative inode.
1860071       // 
1860072       file->references = 0;
1860073       file->oflags = 0;
1860074       inode_put (file->inode);
1860075       file->inode = NULL;
1860076       // 
1860077       // Remove file descriptor for read.
1860078       // 
1860079       fd_read->file->inode->pipe_ref_read--;
1860080       fd_read->fl_flags = 0;
1860081       fd_read->fd_flags = 0;
1860082       fd_read->file = NULL;
1860083       // 
1860084       // Return an error.
1860085       // 
1860086       errset (EMFILE);  // Too many open files.
1860087       return (-1);
1860088     }
1860089   // 
1860090   // File descriptor allocated: put some data inside
1860091   // the
1860092   // file descriptor item.
1860093   // 
1860094   fd_write->fl_flags = O_WRONLY;
1860095   fd_write->fd_flags = 0;
1860096   fd_write->file = file;
1860097   fd_write->file->offset = 0;
1860098   fd_write->file->inode->pipe_ref_write++;
1860099   // 
1860100   // Save file descriptor numbers inside the
1860101   // `pipefd[]' array.
1860102   // 
1860103   pipefd[0] = fdn_read;
1860104   pipefd[1] = fdn_write;
1860105   // 
1860106   // Ok.
1860107   // 
1860108   return (0);
1860109 }

94.8.29   kernel/lib_s/s_read.c

Si veda la sezione 87.39.

1870001 #include <kernel/proc.h>
1870002 #include <kernel/lib_s.h>
1870003 #include <errno.h>
1870004 #include <fcntl.h>
1870005 //----------------------------------------------------------
1870006 #define DEBUG 0
1870007 //----------------------------------------------------------
1870008 ssize_t
1870009 s_read (pid_t pid, int fdn, void *buffer, size_t count)
1870010 {
1870011   fd_t *fd;
1870012   ssize_t size_read;
1870013   int eof = 0;
1870014   // 
1870015   // Get file descriptor.
1870016   // 
1870017   fd = fd_reference (pid, &fdn);
1870018   if (fd == NULL || fd->file == NULL
1870019       || (fd->file->inode == NULL
1870020           && fd->file->sock == NULL))
1870021     {
1870022       errset (EBADF);   // Bad file descriptor.
1870023       return ((ssize_t) - 1);
1870024     }
1870025   // 
1870026   // Check if it is opened for read.
1870027   // 
1870028   if (!(fd->file->oflags & O_RDONLY))
1870029     {
1870030       // 
1870031       // The file is not opened for read.
1870032       // 
1870033       errset (EINVAL);  // Invalid argument.
1870034       return ((ssize_t) - 1);
1870035     }
1870036   // 
1870037   // Check the kind of file to be read and read it.
1870038   // 
1870039   if (fd->file->sock != NULL)
1870040     {
1870041       // 
1870042       // Read from the socket and return.
1870043       // 
1870044       return (s_recvfrom
1870045               (pid, fdn, buffer, count, 0, NULL, NULL));
1870046     }
1870047   else if (S_ISBLK (fd->file->inode->mode)
1870048            || S_ISCHR (fd->file->inode->mode))
1870049     {
1870050       // 
1870051       // A device is to be read.
1870052       // 
1870053       size_read =
1870054         dev_io (pid,
1870055                 (dev_t) fd->file->inode->direct[0],
1870056                 DEV_READ, fd->file->offset, buffer,
1870057                 count, &eof);
1870058       if (size_read < 0
1870059           && (errno == EAGAIN || errno == EWOULDBLOCK))
1870060         {
1870061           if (fd->fl_flags & O_NONBLOCK)
1870062             {
1870063               // 
1870064               // Non blocking null read.
1870065               // 
1870066               ;
1870067             }
1870068           else
1870069             {
1870070               // 
1870071               // Null read: put the process to sleep.
1870072               // 
1870073               proc_table[pid].status = PROC_SLEEPING;
1870074               proc_table[pid].ret = 0;
1870075               proc_table[pid].wakeup_events =
1870076                 WAKEUP_EVENT_DEV_READ;
1870077               proc_table[pid].wakeup_dev =
1870078                 fd->file->inode->direct[0];
1870079               if (DEBUG)
1870080                 {
1870081                   k_printf
1870082                     ("[%s] PID %i goes to sleep "
1870083                      "waiting to read from a "
1870084                      "device.\n", __FILE__, pid);
1870085                 }
1870086             }
1870087         }
1870088     }
1870089   else if (S_ISREG (fd->file->inode->mode))
1870090     {
1870091       // 
1870092       // A regular file is to be read.
1870093       // 
1870094       size_read =
1870095         inode_file_read (fd->file->inode,
1870096                          fd->file->offset, buffer,
1870097                          count, &eof);
1870098     }
1870099   else if (S_ISDIR (fd->file->inode->mode))
1870100     {
1870101       // 
1870102       // A directory, is to be read.
1870103       // 
1870104       size_read =
1870105         inode_file_read (fd->file->inode,
1870106                          fd->file->offset, buffer,
1870107                          count, &eof);
1870108     }
1870109   else if (S_ISFIFO (fd->file->inode->mode))
1870110     {
1870111       // 
1870112       // A pipe, is to be read.
1870113       // 
1870114       size_read =
1870115         inode_pipe_read (fd->file->inode, buffer,
1870116                          count, &eof);
1870117       // 
1870118       if (size_read == 0)
1870119         {
1870120           // 
1870121           // Check what to do.
1870122           // 
1870123           if (fd->file->inode->pipe_ref_write == 0)
1870124             {
1870125               // 
1870126               // EOF, if it is a valid pointer, is
1870127               // already
1870128               // set by `inode_pipe_read()', if is
1870129               // time to
1870130               // set it.
1870131               // 
1870132               // Wake up processes waiting to write.
1870133               // 
1870134               proc_wakeup_pipe_write (fd->file->inode);
1870135               // 
1870136               return (size_read);
1870137             }
1870138           else
1870139             {
1870140               // 
1870141               // Go to sleep.
1870142               // 
1870143               proc_table[pid].status = PROC_SLEEPING;
1870144               proc_table[pid].ret = 0;
1870145               proc_table[pid].wakeup_inode =
1870146                 fd->file->inode;
1870147               proc_table[pid].wakeup_events =
1870148                 WAKEUP_EVENT_PIPE_READ;
1870149               if (DEBUG)
1870150                 {
1870151                   k_printf
1870152                     ("[%s] PID %i goes to sleep "
1870153                      "waiting to read from a pipe.\n",
1870154                      __FILE__, pid);
1870155                 }
1870156             }
1870157         }
1870158       else
1870159         {
1870160           // 
1870161           // Wake up processes waiting to write.
1870162           // 
1870163           proc_wakeup_pipe_write (fd->file->inode);
1870164         }
1870165     }
1870166   else
1870167     {
1870168       // 
1870169       // Unsupported file type.
1870170       // 
1870171       errset (E_FILE_TYPE_UNSUPPORTED); // File type
1870172       // unsupported.
1870173       return ((ssize_t) - 1);
1870174     }
1870175   // 
1870176   // Update the file descriptor internal offset, if
1870177   // there is an inode.
1870178   // 
1870179   if (fd->file->inode != NULL && size_read > 0)
1870180     {
1870181       fd->file->offset += size_read;
1870182     }
1870183   // 
1870184   // Return the size read, even if it is an error.
1870185   // Please notice
1870186   // that a size of zero might be related to an end of 
1870187   // file, or
1870188   // just that the read should be retried. For the
1870189   // latter case,
1870190   // -1 is returned with error EAGAIN, so that the
1870191   // function
1870192   // `read()' can retry.
1870193   // 
1870194   if (size_read == 0 && !eof)
1870195     {
1870196       errset (EAGAIN);
1870197       return (-1);
1870198     }
1870199   else
1870200     {
1870201       return (size_read);
1870202     }
1870203 }

94.8.30   kernel/lib_s/s_recvfrom.c

Si veda la sezione 87.40.

1880001 #include <fcntl.h>
1880002 #include <kernel/proc.h>
1880003 #include <kernel/net.h>
1880004 #include <kernel/net/route.h>
1880005 #include <errno.h>
1880006 #include <arpa/inet.h>
1880007 #include <sys/os32.h>
1880008 #include <netinet/udp.h>
1880009 //----------------------------------------------------------
1880010 #define DEBUG 0
1880011 //----------------------------------------------------------
1880012 ssize_t
1880013 s_recvfrom (pid_t pid, int sfdn, void *buffer,
1880014             size_t length, int flags,
1880015             struct sockaddr *addrfrom, socklen_t * addrlen)
1880016 {
1880017   fd_t *sfd;
1880018   int i;        // IP table index.
1880019   size_t size_read;
1880020   struct udphdr *udp;
1880021   void *data;
1880022   struct sockaddr_in *addrfrom_in = (void *) addrfrom;
1880023   // 
1880024   // Get file descriptor and verify that it is a
1880025   // socket.
1880026   // 
1880027   sfd = fd_reference (pid, &sfdn);
1880028   if (sfd == NULL || sfd->file == NULL)
1880029     {
1880030       errset (EBADF);   // Bad file descriptor.
1880031       return ((ssize_t) - 1);
1880032     }
1880033   if (sfd->file->sock == NULL)
1880034     {
1880035       errset (ENOTSOCK);        // Not a socket.
1880036       return ((ssize_t) - 1);
1880037     }
1880038   // 
1880039   // Verify to have a valid buffer pointer.
1880040   // 
1880041   if (buffer == NULL)
1880042     {
1880043       errset (EINVAL);
1880044       return ((ssize_t) - 1);
1880045     }
1880046   // 
1880047   // 
1880048   // 
1880049   if (sfd->file->sock->family == AF_INET)
1880050     {
1880051       // 
1880052       // INET
1880053       // 
1880054       // Should do some check here...
1880055       // 
1880056       if (sfd->file->sock->type == SOCK_RAW)
1880057         {
1880058           // 
1880059           // RAW
1880060           // 
1880061           if (sfd->file->sock->protocol == IPPROTO_ICMP)
1880062             {
1880063               // 
1880064               // ICMP
1880065               // 
1880066               // 
1880067               // Scan the ip_table[] to find an ICMP
1880068               // packet
1880069               // that was not already seen by the
1880070               // socket.
1880071               // 
1880072               for (i = 0; i < IP_MAX_PACKETS; i++)
1880073                 {
1880074                   // 
1880075                   // Check the protocol.
1880076                   // 
1880077                   if (ip_table[i].packet.header.protocol !=
1880078                       IPPROTO_ICMP)
1880079                     {
1880080                       // 
1880081                       // It is not ICMP.
1880082                       // 
1880083                       continue;
1880084                     }
1880085                   // 
1880086                   // Is the packet new for the socket?
1880087                   // 
1880088                   // Please notice that the kernel
1880089                   // might be interrupted
1880090                   // also between clock tics; so,
1880091                   // during a single clock
1880092                   // time, a new packet might be
1880093                   // reached.
1880094                   // 
1880095                   if (ip_table[i].clock
1880096                       < sfd->file->sock->read.clock[i])
1880097                     {
1880098                       // 
1880099                       // Already seen or packet too
1880100                       // old.
1880101                       // 
1880102                       continue;
1880103                     }
1880104                   // 
1880105                   // Verify the IP addresses.
1880106                   // 
1880107                   if (ip_table[i].packet.header.daddr
1880108                       != htonl (sfd->file->sock->laddr)
1880109                       && sfd->file->sock->laddr != 0)
1880110                     {
1880111                       // 
1880112                       // The local address does not
1880113                       // match, and it is
1880114                       // not zero.
1880115                       // 
1880116                       continue;
1880117                     }
1880118                   // 
1880119                   if (ip_table[i].packet.header.saddr
1880120                       != htonl (sfd->file->sock->raddr))
1880121                     {
1880122                       // 
1880123                       // The remote address does not
1880124                       // match, but
1880125                       // if it is zero, we accept all.
1880126                       // 
1880127                       if (sfd->file->sock->raddr == 0)
1880128                         {
1880129                           // 
1880130                           // Can accept the packet.
1880131                           // 
1880132                           ;
1880133                         }
1880134                       else
1880135                         {
1880136                           continue;
1880137                         }
1880138                     }
1880139                   // 
1880140                   // Packet accepted.
1880141                   // 
1880142                   // This ICMP RAW packet is new for
1880143                   // the
1880144                   // socket: save the clock time, so
1880145                   // that the
1880146                   // same packet is not read again.
1880147                   // 
1880148                   sfd->file->sock->read.clock[i]
1880149                     = ip_table[i].clock;
1880150                   // 
1880151                   // Copy the packet.
1880152                   // 
1880153                   size_read
1880154                     =
1880155                     min (ntohs
1880156                          (ip_table[i].packet.header.
1880157                           tot_len), length);
1880158                   // 
1880159                   memcpy (buffer,
1880160                           ip_table[i].packet.octet,
1880161                           size_read);
1880162                   // 
1880163                   // Get the source address and
1880164                   // return.
1880165                   // 
1880166                   if (addrfrom != NULL && addrlen != NULL)
1880167                     {
1880168                       if (*addrlen >=
1880169                           sizeof (struct sockaddr_in))
1880170                         {
1880171                           addrfrom_in->sin_family = AF_INET;
1880172                           addrfrom_in->sin_port = 0;
1880173                           addrfrom_in->sin_addr.s_addr
1880174                             =
1880175                             ip_table[i].packet.header.saddr;
1880176                         }
1880177                       *addrlen =
1880178                         sizeof (struct sockaddr_in);
1880179                     }
1880180                   return ((ssize_t) size_read);
1880181                 }
1880182             }
1880183           else
1880184             {
1880185               // 
1880186               // Unsupported protocol.
1880187               // 
1880188               errset (EPROTONOSUPPORT);
1880189               return ((ssize_t) - 1);
1880190             }
1880191         }
1880192       else if (sfd->file->sock->type == SOCK_DGRAM)
1880193         {
1880194           // 
1880195           // DGRAM
1880196           // 
1880197           if (sfd->file->sock->protocol == IPPROTO_UDP)
1880198             {
1880199               // 
1880200               // UDP
1880201               // 
1880202               // Scan the ip_table[] to find an UDP
1880203               // packet
1880204               // that was not already seen by the
1880205               // socket.
1880206               // 
1880207               for (i = 0; i < IP_MAX_PACKETS; i++)
1880208                 {
1880209                   // 
1880210                   // Check the protocol.
1880211                   // 
1880212                   if (ip_table[i].packet.header.protocol !=
1880213                       IPPROTO_UDP)
1880214                     {
1880215                       // 
1880216                       // It is not UDP.
1880217                       // 
1880218                       continue;
1880219                     }
1880220                   // 
1880221                   // Is the packet new for the socket?
1880222                   // 
1880223                   // Please notice that the kernel
1880224                   // might be interrupted
1880225                   // also between clock tics; so,
1880226                   // during a single clock
1880227                   // time, a new packet might be
1880228                   // reached.
1880229                   // 
1880230                   if (ip_table[i].clock
1880231                       < sfd->file->sock->read.clock[i])
1880232                     {
1880233                       // 
1880234                       // Already seen or packet too
1880235                       // old.
1880236                       // 
1880237                       continue;
1880238                     }
1880239                   // 
1880240                   // Verify the ports.
1880241                   // 
1880242                   udp = (struct udphdr *)
1880243                     &ip_table[i].packet.octet
1880244                     [sizeof (struct iphdr)];
1880245                   // 
1880246                   if (udp->dest == 0)
1880247                     {
1880248                       // 
1880249                       // Cannot accept packets for the 
1880250                       // port zero!
1880251                       // 
1880252                       continue;
1880253                     }
1880254                   // 
1880255                   if (udp->dest !=
1880256                       htons (sfd->file->sock->lport))
1880257                     {
1880258                       // 
1880259                       // The local port does not
1880260                       // match!
1880261                       // 
1880262                       continue;
1880263                     }
1880264                   // 
1880265                   if (udp->source !=
1880266                       htons (sfd->file->sock->rport)
1880267                       && sfd->file->sock->rport != 0)
1880268                     {
1880269                       // 
1880270                       // The remote port does not
1880271                       // match, and is not
1880272                       // zero.
1880273                       // 
1880274                       continue;
1880275                     }
1880276                   // 
1880277                   // Verify the IP addresses.
1880278                   // 
1880279                   if (ip_table[i].packet.header.daddr
1880280                       != htonl (sfd->file->sock->laddr)
1880281                       && sfd->file->sock->laddr != 0)
1880282                     {
1880283                       // 
1880284                       // The local address does not
1880285                       // match, and is
1880286                       // not zero.
1880287                       // 
1880288                       continue;
1880289                     }
1880290                   // 
1880291                   if (ip_table[i].packet.header.saddr
1880292                       != htonl (sfd->file->sock->raddr)
1880293                       && sfd->file->sock->raddr != 0)
1880294                     {
1880295                       // 
1880296                       // The remote address does not
1880297                       // match, and is
1880298                       // not zero.
1880299                       // 
1880300                       continue;
1880301                     }
1880302                   // 
1880303                   // The packet is accepted.
1880304                   // 
1880305                   // This UDP packet is new for the
1880306                   // socket:
1880307                   // save the clock time, so that the
1880308                   // same packet is not read again.
1880309                   // 
1880310                   sfd->file->sock->read.clock[i]
1880311                     = ip_table[i].clock;
1880312                   // 
1880313                   // Check the right minimal size to
1880314                   // be read, comparing
1880315                   // the size of the IP packet, the
1880316                   // size of the UDP
1880317                   // packet and the size requested.
1880318                   // 
1880319                   size_read =
1880320                     ntohs (ip_table[i].packet.header.
1880321                            tot_len) -
1880322                     (ip_table[i].packet.header.ihl * 4) -
1880323                     (sizeof (struct udphdr));
1880324                   size_read =
1880325                     min (size_read,
1880326                          (udp->len -
1880327                           sizeof (struct udphdr)));
1880328                   size_read = min (size_read, length);
1880329                   // 
1880330                   // Copy the data inside the UDP
1880331                   // packet.
1880332                   // 
1880333                   data =
1880334                     (((uint8_t *) udp) +
1880335                      sizeof (struct udphdr));
1880336                   // 
1880337                   memcpy (buffer, data, size_read);
1880338                   // 
1880339                   // Get the source address and
1880340                   // return.
1880341                   // 
1880342                   if (addrfrom != NULL && addrlen != NULL)
1880343                     {
1880344                       if (*addrlen >=
1880345                           sizeof (struct sockaddr_in))
1880346                         {
1880347                           addrfrom_in->sin_family = AF_INET;
1880348                           addrfrom_in->sin_port =
1880349                             udp->source;
1880350                           addrfrom_in->sin_addr.s_addr =
1880351                             ip_table[i].packet.header.saddr;
1880352                         }
1880353                       *addrlen =
1880354                         sizeof (struct sockaddr_in);
1880355                     }
1880356                   return ((ssize_t) size_read);
1880357                 }
1880358             }
1880359         }
1880360       else if (sfd->file->sock->type == SOCK_STREAM)
1880361         {
1880362           // 
1880363           // STREAM
1880364           // 
1880365           if (sfd->file->sock->protocol == IPPROTO_TCP)
1880366             {
1880367               // 
1880368               // TCP
1880369               // 
1880370               // See if the read side of the stream
1880371               // was closed.
1880372               // 
1880373               if (sfd->file->sock->tcp.recv_closed
1880374                   || sfd->file->sock->tcp.conn == TCP_CLOSE)
1880375                 {
1880376                   // 
1880377                   // If the `recv_size' is zero, the
1880378                   // stream
1880379                   // is closed.
1880380                   // 
1880381                   if (sfd->file->sock->tcp.recv_size
1880382                       == 0
1880383                       || sfd->file->sock->tcp.can_read == 0)
1880384                     {
1880385                       // 
1880386                       // End of file.
1880387                       // 
1880388                       return ((ssize_t) 0);
1880389                     }
1880390                 }
1880391               // 
1880392               // At the moment, nothing was read.
1880393               // 
1880394               size_read = 0;
1880395               // 
1880396               // See if there is data to be read from
1880397               // the stream.
1880398               // 
1880399               if (sfd->file->sock->tcp.can_read)
1880400                 {
1880401                   size_read =
1880402                     min (sfd->file->sock->tcp.recv_size,
1880403                          length);
1880404                   memcpy (buffer,
1880405                           sfd->file->sock->tcp.recv_index,
1880406                           size_read);
1880407                   // 
1880408                   sfd->file->sock->tcp.recv_size -=
1880409                     size_read;
1880410                   sfd->file->sock->tcp.recv_index +=
1880411                     size_read;
1880412                   // 
1880413                   if (sfd->file->sock->tcp.recv_size == 0)
1880414                     {
1880415                       // 
1880416                       // Nothing to be read at the
1880417                       // moment.
1880418                       // 
1880419                       sfd->file->sock->tcp.can_read = 0;
1880420                       sfd->file->sock->tcp.can_recv = 1;
1880421                     }
1880422                   // 
1880423                   // Get the source address and
1880424                   // return.
1880425                   // 
1880426                   if (addrfrom != NULL && addrlen != NULL)
1880427                     {
1880428                       if (*addrlen >=
1880429                           sizeof (struct sockaddr_in))
1880430                         {
1880431                           addrfrom_in->sin_family = AF_INET;
1880432                           addrfrom_in->sin_port =
1880433                             htons (sfd->file->sock->rport);
1880434                           addrfrom_in->sin_addr.s_addr =
1880435                             htons (sfd->file->sock->raddr);
1880436                         }
1880437                       *addrlen =
1880438                         sizeof (struct sockaddr_in);
1880439                     }
1880440                 }
1880441               // 
1880442               // Check if something was read.
1880443               // 
1880444               if (size_read > 0)
1880445                 {
1880446                   // 
1880447                   // Return normally.
1880448                   // 
1880449                   return ((ssize_t) size_read);
1880450                 }
1880451               else
1880452                 {
1880453                   // 
1880454                   // Nothing to be read at the moment.
1880455                   // 
1880456                   if (sfd->fl_flags & O_NONBLOCK)
1880457                     {
1880458                       // 
1880459                       // Try again.
1880460                       // 
1880461                       errset (EAGAIN);
1880462                       return ((ssize_t) - 1);
1880463                     }
1880464                   else
1880465                     {
1880466                       // 
1880467                       // Go to sleep and return a
1880468                       // temporary error.
1880469                       // 
1880470                       proc_table[pid].status =
1880471                         PROC_SLEEPING;
1880472                       proc_table[pid].ret = 0;
1880473                       proc_table[pid].wakeup_events
1880474                         = WAKEUP_EVENT_SOCK_READ;
1880475                       proc_table[pid].wakeup_sock =
1880476                         sfd->file->sock;
1880477                       if (DEBUG)
1880478                         {
1880479                           k_printf
1880480                             ("[%s:%i] PID %i goes to "
1880481                              "sleep waiting to "
1880482                              "receive for a socket.\n",
1880483                              __FILE__, __LINE__, pid);
1880484                         }
1880485                       // 
1880486                       // Nothing was received.
1880487                       // 
1880488                       errset (EAGAIN);
1880489                       return ((ssize_t) - 1);
1880490                     }
1880491                 }
1880492             }
1880493           else
1880494             {
1880495               // 
1880496               // Unsupported protocol.
1880497               // 
1880498               errset (EPROTONOSUPPORT);
1880499               return ((ssize_t) - 1);
1880500             }
1880501         }
1880502       else
1880503         {
1880504           // 
1880505           // Unsupported type.
1880506           // 
1880507           errset (EPROTONOSUPPORT);
1880508           return ((ssize_t) - 1);
1880509         }
1880510     }
1880511   else
1880512     {
1880513       // 
1880514       // Unsupported family.
1880515       // 
1880516       errset (EAFNOSUPPORT);
1880517       return ((ssize_t) - 1);
1880518     }
1880519   // 
1880520   // If we are here, there are no more packets to read 
1880521   // at the moment.
1880522   // 
1880523   if (sfd->fl_flags & O_NONBLOCK)
1880524     {
1880525       // 
1880526       // Try again.
1880527       // 
1880528       errset (EAGAIN);
1880529       return (-1);
1880530     }
1880531   else
1880532     {
1880533       // 
1880534       // The process should go to sleep.
1880535       // 
1880536       proc_table[pid].status = PROC_SLEEPING;
1880537       proc_table[pid].ret = 0;
1880538       proc_table[pid].wakeup_events =
1880539         WAKEUP_EVENT_SOCK_READ;
1880540       proc_table[pid].wakeup_sock = sfd->file->sock;
1880541       if (DEBUG)
1880542         {
1880543           k_printf ("[%s:%i] PID %i goes to sleep "
1880544                     "waiting to receive "
1880545                     "for a socket.\n",
1880546                     __FILE__, __LINE__, pid);
1880547         }
1880548       // 
1880549       // Try again.
1880550       // 
1880551       errset (EAGAIN);
1880552       return ((ssize_t) - 1);
1880553     }
1880554 }

94.8.31   kernel/lib_s/s_routeadd.c

Si veda la sezione 87.42.

1890001 #include <arpa/inet.h>
1890002 #include <sys/os32.h>
1890003 #include <kernel/net/route.h>
1890004 #include <kernel/lib_k.h>
1890005 #include <errno.h>
1890006 #include <netinet/in.h>
1890007 #include <kernel/proc.h>
1890008 //----------------------------------------------------------
1890009 // This syscall is present only inside os32.
1890010 //----------------------------------------------------------
1890011 int
1890012 s_routeadd (pid_t pid, in_addr_t dest, int m,
1890013             in_addr_t router, int device)
1890014 {
1890015   int r;
1890016   h_addr_t netmask;
1890017   h_addr_t network;
1890018   // 
1890019   // Must be a privileged process.
1890020   // 
1890021   if (proc_table[pid].euid != 0)
1890022     {
1890023       errset (EPERM);
1890024       return (-1);
1890025     }
1890026   // 
1890027   // 
1890028   // 
1890029   if (m > 32 || m < 0)
1890030     {
1890031       errset (EINVAL);
1890032       return (-1);
1890033     }
1890034   // 
1890035   // Calculate the netmask.
1890036   // 
1890037   netmask = ip_mask (m);
1890038   // 
1890039   // Fix the destination address, with the mask.
1890040   // 
1890041   network = ntohl (dest) & netmask;
1890042   // 
1890043   // Check if there is already. If there is: update
1890044   // it.
1890045   // 
1890046   for (r = 0; r < ROUTE_MAX_ROUTES; r++)
1890047     {
1890048       if (network == route_table[r].network
1890049           && m == route_table[r].m)
1890050         {
1890051           // 
1890052           // Update.
1890053           // 
1890054           route_table[r].router = ntohl (router);
1890055           route_table[r].netmask = netmask;
1890056           route_table[r].interface = device;
1890057           return (0);
1890058         }
1890059     }
1890060   // 
1890061   // The item is new. Find an empty place.
1890062   // 
1890063   for (r = 0; r < ROUTE_MAX_ROUTES; r++)
1890064     {
1890065       if (route_table[r].network == 0xFFFFFFFF)
1890066         {
1890067           // 
1890068           // Empty.
1890069           // 
1890070           route_table[r].network = network;
1890071           route_table[r].netmask = netmask;
1890072           route_table[r].m = m;
1890073           route_table[r].router = ntohl (router);
1890074           route_table[r].interface = device;
1890075           // 
1890076           route_sort ();
1890077           // 
1890078           return (0);
1890079         }
1890080     }
1890081   // 
1890082   // No free space found.
1890083   // 
1890084   errset (ENOMEM);
1890085   return (-1);
1890086 }

94.8.32   kernel/lib_s/s_routedel.c

Si veda la sezione 87.43.

1900001 #include <arpa/inet.h>
1900002 #include <sys/os32.h>
1900003 #include <kernel/net/route.h>
1900004 #include <kernel/lib_k.h>
1900005 #include <errno.h>
1900006 #include <netinet/in.h>
1900007 #include <kernel/proc.h>
1900008 //----------------------------------------------------------
1900009 // This syscall is present only inside os32.
1900010 //----------------------------------------------------------
1900011 int
1900012 s_routedel (pid_t pid, in_addr_t dest, int m)
1900013 {
1900014   int r;
1900015   h_addr_t network;
1900016   // 
1900017   // Must be a privileged process.
1900018   // 
1900019   if (proc_table[pid].euid != 0)
1900020     {
1900021       errset (EPERM);
1900022       return (-1);
1900023     }
1900024   // 
1900025   // 
1900026   // 
1900027   if (m > 32 || m < 0)
1900028     {
1900029       errset (EINVAL);
1900030       return (-1);
1900031     }
1900032   // 
1900033   // Calculate the destination network with the mask.
1900034   // 
1900035   network = ntohl (dest) & ip_mask (m);
1900036   // 
1900037   // Check if there is already. If there is: remove
1900038   // it.
1900039   // 
1900040   for (r = 0; r < ROUTE_MAX_ROUTES; r++)
1900041     {
1900042       if (network == route_table[r].network
1900043           && m == route_table[r].m)
1900044         {
1900045           // 
1900046           // Remove.
1900047           // 
1900048           memset (&route_table[m], 0xFF,
1900049                   sizeof (route_table[m]));
1900050           return (0);
1900051         }
1900052     }
1900053   // 
1900054   // Not found.
1900055   // 
1900056   errset (EINVAL);
1900057   return (-1);
1900058 }

94.8.33   kernel/lib_s/s_sbrk.c

Si veda la sezione 87.5.

1910001 #include <errno.h>
1910002 #include <kernel/proc.h>
1910003 #include <kernel/lib_k.h>
1910004 #include <kernel/lib_s.h>
1910005 //----------------------------------------------------------
1910006 void *
1910007 s_sbrk (pid_t pid, intptr_t increment)
1910008 {
1910009   size_t previous_size;
1910010   size_t new_size;
1910011   int status;
1910012   // 
1910013   // Get current data segment full size.
1910014   // 
1910015   if (proc_table[pid].domain_data == 0)
1910016     {
1910017       previous_size = (proc_table[pid].domain_text
1910018                        + proc_table[pid].extra_data);
1910019     }
1910020   else
1910021     {
1910022       previous_size = (proc_table[pid].domain_data
1910023                        + proc_table[pid].extra_data);
1910024     }
1910025   // 
1910026   // Check increment.
1910027   // 
1910028   if ((increment + proc_table[pid].extra_data) < 0)
1910029     {
1910030       // 
1910031       // Cannot reduce too much. Just correct it.
1910032       // 
1910033       increment = -proc_table[pid].extra_data;
1910034     }
1910035   // 
1910036   // Calculate the new size.
1910037   // 
1910038   new_size = previous_size + increment;
1910039   // 
1910040   // Call `s_brk()' to do the work. The new size value 
1910041   // is the
1910042   // same of the new requested pointer address.
1910043   // 
1910044   status = s_brk (pid, (void *) new_size);
1910045   // 
1910046   if (status < 0)
1910047     {
1910048       errset (errno);
1910049       return ((void *) -1);
1910050     }
1910051   // 
1910052   // Ok: return previous final address.
1910053   // 
1910054   return ((void *) previous_size);
1910055 }

94.8.34   kernel/lib_s/s_send.c

Si veda la sezione 87.45.

1920001 #include <kernel/proc.h>
1920002 #include <kernel/net.h>
1920003 #include <kernel/net/route.h>
1920004 #include <kernel/net/udp.h>
1920005 #include <errno.h>
1920006 #include <arpa/inet.h>
1920007 #include <fcntl.h>
1920008 #include <sys/os32.h>
1920009 //----------------------------------------------------------
1920010 #define DEBUG 0
1920011 //----------------------------------------------------------
1920012 ssize_t
1920013 s_send (pid_t pid, int sfdn, const void *buffer,
1920014         size_t size, int flags)
1920015 {
1920016   fd_t *sfd;
1920017   int status;
1920018   // 
1920019   // Get file descriptor and verify that it is a
1920020   // socket.
1920021   // 
1920022   sfd = fd_reference (pid, &sfdn);
1920023   if (sfd == NULL || sfd->file == NULL)
1920024     {
1920025       errset (EBADF);   // Bad file descriptor.
1920026       return ((ssize_t) - 1);
1920027     }
1920028   if (sfd->file->sock == NULL)
1920029     {
1920030       errset (ENOTSOCK);        // Not a socket.
1920031       return ((ssize_t) - 1);
1920032     }
1920033   if (sfd->file->sock->unreach_port)
1920034     {
1920035       errset (ECONNREFUSED);    // Connection refused.
1920036       return ((ssize_t) - 1);
1920037     }
1920038   if (sfd->file->sock->unreach_prot)
1920039     {
1920040       errset (ENOPROTOOPT);     // Protocol not
1920041       // available.
1920042       return ((ssize_t) - 1);
1920043     }
1920044   if (sfd->file->sock->unreach_host)
1920045     {
1920046       errset (EHOSTUNREACH);    // Host unreachable.
1920047       return ((ssize_t) - 1);
1920048     }
1920049   if (sfd->file->sock->unreach_net)
1920050     {
1920051       errset (ENETUNREACH);     // Net unreachable.
1920052       return ((ssize_t) - 1);
1920053     }
1920054   // 
1920055   // Verify to have a valid buffer pointer.
1920056   // 
1920057   if (buffer == NULL)
1920058     {
1920059       errset (EINVAL);
1920060       return ((ssize_t) - 1);
1920061     }
1920062   // 
1920063   // 
1920064   // 
1920065   if (sfd->file->sock->family == AF_INET)
1920066     {
1920067       // 
1920068       // INET
1920069       // 
1920070       // AF_INET requires at least the remote address.
1920071       // 
1920072       if (sfd->file->sock->raddr == 0)
1920073         {
1920074           errset (EDESTADDRREQ);
1920075           return ((ssize_t) - 1);
1920076         }
1920077       // 
1920078       if (sfd->file->sock->type == SOCK_RAW)
1920079         {
1920080           // 
1920081           // RAW
1920082           // 
1920083           if (sfd->file->sock->protocol == IPPROTO_ICMP)
1920084             {
1920085               // 
1920086               // ICMP
1920087               // 
1920088               status = ip_tx (sfd->file->sock->laddr,
1920089                               sfd->file->sock->raddr,
1920090                               sfd->file->sock->protocol,
1920091                               buffer, size);
1920092               if (status)
1920093                 {
1920094                   errset (errno);
1920095                   return ((ssize_t) - 1);
1920096                 }
1920097               else
1920098                 {
1920099                   return ((ssize_t) size);
1920100                 }
1920101             }
1920102           else
1920103             {
1920104               // 
1920105               // Unsupported protocol.
1920106               // 
1920107               errset (EPROTONOSUPPORT);
1920108               return ((ssize_t) - 1);
1920109             }
1920110         }
1920111       else if (sfd->file->sock->type == SOCK_DGRAM)
1920112         {
1920113           // 
1920114           // DGRAM
1920115           // 
1920116           if (sfd->file->sock->protocol == IPPROTO_UDP)
1920117             {
1920118               // 
1920119               // UDP
1920120               // 
1920121               status = udp_tx (sfd->file->sock->lport,
1920122                                sfd->file->sock->rport,
1920123                                sfd->file->sock->laddr,
1920124                                sfd->file->sock->raddr,
1920125                                buffer, size);
1920126               if (status)
1920127                 {
1920128                   errset (errno);
1920129                   return ((ssize_t) - 1);
1920130                 }
1920131               else
1920132                 {
1920133                   return ((ssize_t) size);
1920134                 }
1920135             }
1920136           else
1920137             {
1920138               // 
1920139               // Unsupported protocol.
1920140               // 
1920141               errset (EPROTONOSUPPORT);
1920142               return ((ssize_t) - 1);
1920143             }
1920144         }
1920145       else if (sfd->file->sock->type == SOCK_STREAM)
1920146         {
1920147           // 
1920148           // STREAM
1920149           // 
1920150           if (sfd->file->sock->protocol == IPPROTO_TCP)
1920151             {
1920152               // 
1920153               // TCP
1920154               // 
1920155               // See if the send side of the stream
1920156               // was closed.
1920157               // 
1920158               if (sfd->file->sock->tcp.send_closed
1920159                   || sfd->file->sock->tcp.conn == TCP_CLOSE)
1920160                 {
1920161                   // 
1920162                   // End of file.
1920163                   // 
1920164                   if (DEBUG)
1920165                     {
1920166                       k_printf ("end of socket write\n");
1920167                     }
1920168                   s_kill ((pid_t) 0, pid, SIGPIPE);
1920169                   errset (EPIPE);
1920170                   return ((ssize_t) - 1);
1920171                 }
1920172               // 
1920173               // Put data to the send buffer, if it is 
1920174               // possible.
1920175               // 
1920176               if (sfd->file->sock->tcp.can_write)
1920177                 {
1920178                   size =
1920179                     min (size,
1920180                          (TCP_MSS -
1920181                           sizeof (struct tcphdr)));
1920182                   memcpy (sfd->file->sock->tcp.send_data,
1920183                           buffer, size);
1920184                   sfd->file->sock->tcp.send_size = size;
1920185                   sfd->file->sock->tcp.can_write = 0;
1920186                   sfd->file->sock->tcp.can_send = 1;
1920187                   // 
1920188                   sfd->file->sock->tcp.lsq[++sfd->
1920189                                            file->sock->tcp.
1920190                                            lsqi] =
1920191                     sfd->file->sock->tcp.lsq_ack;
1920192                   sfd->file->sock->tcp.send_flags =
1920193                     TCP_FLAG_PSH | TCP_FLAG_ACK;
1920194                   tcp_tx_sock (sfd->file->sock);
1920195                   // 
1920196                   return ((ssize_t) size);
1920197                 }
1920198               else
1920199                 {
1920200                   // 
1920201                   // At the moment, nothing can be
1920202                   // written.
1920203                   // 
1920204                   if (sfd->fl_flags & O_NONBLOCK)
1920205                     {
1920206                       // 
1920207                       // Cannot block.
1920208                       // 
1920209                       errset (EAGAIN);
1920210                       return ((ssize_t) - 1);
1920211                     }
1920212                   else
1920213                     {
1920214                       // 
1920215                       // Go to sleep and return zero.
1920216                       // 
1920217                       proc_table[pid].status =
1920218                         PROC_SLEEPING;
1920219                       proc_table[pid].ret = 0;
1920220                       proc_table[pid].wakeup_events
1920221                         = WAKEUP_EVENT_SOCK_WRITE;
1920222                       proc_table[pid].wakeup_sock =
1920223                         sfd->file->sock;
1920224                       if (DEBUG)
1920225                         {
1920226                           k_printf
1920227                             ("[%s] PID %i goes to "
1920228                              "sleep waiting to write "
1920229                              "to a socket.\n",
1920230                              __FILE__, pid);
1920231                         }
1920232                       // 
1920233                       // Retry.
1920234                       // 
1920235                       errset (EAGAIN);
1920236                       return ((ssize_t) - 1);
1920237                     }
1920238                 }
1920239             }
1920240           else
1920241             {
1920242               // 
1920243               // Unsupported protocol.
1920244               // 
1920245               errset (EPROTONOSUPPORT);
1920246               return ((ssize_t) - 1);
1920247             }
1920248         }
1920249       else
1920250         {
1920251           // 
1920252           // Unsupported type.
1920253           // 
1920254           errset (EPROTONOSUPPORT);
1920255           return ((ssize_t) - 1);
1920256         }
1920257     }
1920258   else
1920259     {
1920260       // 
1920261       // Unsupported family.
1920262       // 
1920263       errset (EAFNOSUPPORT);
1920264       return ((ssize_t) - 1);
1920265     }
1920266 }

94.8.35   kernel/lib_s/s_setegid.c

Si veda la sezione 87.48.

1930001 #include <kernel/proc.h>
1930002 #include <kernel/lib_s.h>
1930003 #include <errno.h>
1930004 //----------------------------------------------------------
1930005 int
1930006 s_setegid (pid_t pid, gid_t egid)
1930007 {
1930008   if ((proc_table[pid].euid == 0)
1930009       || (proc_table[pid].egid == 0))
1930010     {
1930011       proc_table[pid].egid = egid;
1930012       return (0);
1930013     }
1930014   else if (egid == proc_table[pid].egid)
1930015     {
1930016       return (0);
1930017     }
1930018   else if (egid == proc_table[pid].gid
1930019            || egid == proc_table[pid].sgid)
1930020     {
1930021       proc_table[pid].egid = egid;
1930022       return (0);
1930023     }
1930024   else
1930025     {
1930026       errset (EPERM);
1930027       return (-1);
1930028     }
1930029 }

94.8.36   kernel/lib_s/s_seteuid.c

Si veda la sezione 87.51.

1940001 #include <kernel/proc.h>
1940002 #include <kernel/lib_s.h>
1940003 #include <errno.h>
1940004 //----------------------------------------------------------
1940005 int
1940006 s_seteuid (pid_t pid, uid_t euid)
1940007 {
1940008   if (proc_table[pid].euid == 0)
1940009     {
1940010       proc_table[pid].euid = euid;
1940011       return (0);
1940012     }
1940013   else if (euid == proc_table[pid].euid)
1940014     {
1940015       return (0);
1940016     }
1940017   else if (euid == proc_table[pid].uid
1940018            || euid == proc_table[pid].suid)
1940019     {
1940020       proc_table[pid].euid = euid;
1940021       return (0);
1940022     }
1940023   else
1940024     {
1940025       errset (EPERM);
1940026       return (-1);
1940027     }
1940028 }

94.8.37   kernel/lib_s/s_setgid.c

Si veda la sezione 87.48.

1950001 #include <kernel/proc.h>
1950002 #include <kernel/lib_s.h>
1950003 #include <errno.h>
1950004 //----------------------------------------------------------
1950005 int
1950006 s_setgid (pid_t pid, gid_t gid)
1950007 {
1950008   if ((proc_table[pid].euid == 0)
1950009       || (proc_table[pid].egid == 0))
1950010     {
1950011       proc_table[pid].gid = gid;
1950012       proc_table[pid].egid = gid;
1950013       proc_table[pid].sgid = gid;
1950014       return (0);
1950015     }
1950016   else if (gid == proc_table[pid].egid)
1950017     {
1950018       return (0);
1950019     }
1950020   else if (gid == proc_table[pid].gid
1950021            || gid == proc_table[pid].sgid)
1950022     {
1950023       proc_table[pid].egid = gid;
1950024       return (0);
1950025     }
1950026   else
1950027     {
1950028       errset (EPERM);
1950029       return (-1);
1950030     }
1950031 }

94.8.38   kernel/lib_s/s_setjmp.c

Si veda la sezione 87.49.

1960001 #include <kernel/lib_s.h>
1960002 #include <kernel/proc.h>
1960003 #include <errno.h>
1960004 #include <setjmp.h>
1960005 //----------------------------------------------------------
1960006 extern uint32_t proc_stack_pointer;
1960007 //----------------------------------------------------------
1960008 int
1960009 s_setjmp (pid_t pid, jmp_buf env)
1960010 {
1960011   jmp_stack_t *sp;
1960012   jmp_env_t *jmpenv;
1960013   // 
1960014   // Find where is the process stack in memory, from
1960015   // the kernel point
1960016   // of view. Please notice that the current stack at
1960017   // `proc_stack_pointer' will be saved from the
1960018   // scheduler inside
1960019   // the process table, and current stack saved inside 
1960020   // the process
1960021   // table is not up to date.
1960022   // 
1960023   sp = ptr (pid, (void *) proc_stack_pointer);
1960024   // 
1960025   // Translate the pointer `env', to the kernel point
1960026   // of view.
1960027   // 
1960028   jmpenv = ptr (pid, env);
1960029   // 
1960030   // Save the process stack.
1960031   // 
1960032   jmpenv->eax0 = sp->eax0;
1960033   jmpenv->ecx0 = sp->ecx0;
1960034   jmpenv->edx0 = sp->edx0;
1960035   jmpenv->ebx0 = sp->ebx0;
1960036   jmpenv->ebp0 = sp->ebp0;
1960037   jmpenv->esi0 = sp->esi0;
1960038   jmpenv->edi0 = sp->edi0;
1960039   jmpenv->ds0 = sp->ds0;
1960040   jmpenv->es0 = sp->es0;
1960041   jmpenv->fs0 = sp->fs0;
1960042   jmpenv->gs0 = sp->gs0;
1960043   jmpenv->eflags0 = sp->eflags0;
1960044   jmpenv->cs0 = sp->cs0;
1960045   jmpenv->eip0 = sp->eip0;
1960046   // 
1960047   jmpenv->eip1 = sp->eip1;
1960048   jmpenv->syscallnr = sp->syscallnr;
1960049   jmpenv->msg_pointer = sp->msg_pointer;
1960050   jmpenv->msg_size = sp->msg_size;
1960051   jmpenv->env = sp->env;
1960052   jmpenv->ret = sp->ret;
1960053   jmpenv->ebp1 = sp->ebp1;
1960054   jmpenv->eip2 = sp->eip2;
1960055   // 
1960056   // Save also the stack pointer!
1960057   // 
1960058   jmpenv->esp0 = proc_stack_pointer;
1960059   // 
1960060   return 0;
1960061 }

94.8.39   kernel/lib_s/s_setuid.c

Si veda la sezione 87.51.

1970001 #include <kernel/proc.h>
1970002 #include <kernel/lib_s.h>
1970003 #include <errno.h>
1970004 //----------------------------------------------------------
1970005 int
1970006 s_setuid (pid_t pid, uid_t uid)
1970007 {
1970008   if (proc_table[pid].euid == 0)
1970009     {
1970010       proc_table[pid].uid = uid;
1970011       proc_table[pid].euid = uid;
1970012       proc_table[pid].suid = uid;
1970013       return (0);
1970014     }
1970015   else if (uid == proc_table[pid].euid)
1970016     {
1970017       return (0);
1970018     }
1970019   else if (uid == proc_table[pid].uid
1970020            || uid == proc_table[pid].suid)
1970021     {
1970022       proc_table[pid].euid = uid;
1970023       return (0);
1970024     }
1970025   else
1970026     {
1970027       errset (EPERM);
1970028       return (-1);
1970029     }
1970030 }

94.8.40   kernel/lib_s/s_signal.c

Si veda la sezione 87.52.

1980001 #include <kernel/lib_s.h>
1980002 #include <kernel/proc.h>
1980003 #include <errno.h>
1980004 //----------------------------------------------------------
1980005 sighandler_t
1980006 s_signal (pid_t pid, int sig, sighandler_t handler,
1980007           uintptr_t wrapper)
1980008 {
1980009   unsigned long int flag = 1L << (sig - 1);
1980010   sighandler_t previous;
1980011   // 
1980012   if (sig <= 0)
1980013     {
1980014       errset (EINVAL);
1980015       return (SIG_ERR);
1980016     }
1980017   // 
1980018   if (proc_table[pid].sig_ignore & flag)
1980019     {
1980020       previous = SIG_IGN;
1980021     }
1980022   else if (proc_table[pid].sig_handler[sig] !=
1980023            (uintptr_t) NULL)
1980024     {
1980025       previous =
1980026         (sighandler_t) proc_table[pid].sig_handler[sig];
1980027     }
1980028   else
1980029     {
1980030       previous = SIG_DFL;
1980031     }
1980032   // 
1980033   if (handler == SIG_DFL)
1980034     {
1980035       // 
1980036       // Enable signal.
1980037       // 
1980038       proc_table[pid].sig_ignore &= ~flag;
1980039       // 
1980040       return (previous);
1980041     }
1980042   else if (handler == SIG_IGN)
1980043     {
1980044       // 
1980045       // Disable signal.
1980046       // 
1980047       proc_table[pid].sig_ignore |= flag;
1980048       // 
1980049       return (previous);
1980050     }
1980051   else
1980052     {
1980053       // 
1980054       // Enable signal, store the handler address and
1980055       // the
1980056       // handler-wrapper.
1980057       // 
1980058       proc_table[pid].sig_ignore &= ~flag;
1980059       proc_table[pid].sig_handler[sig] =
1980060         (uintptr_t) handler;
1980061       proc_table[pid].sig_handler_wrapper = wrapper;
1980062       // 
1980063       return (previous);
1980064     }
1980065 }

94.8.41   kernel/lib_s/s_socket.c

Si veda la sezione 87.54.

1990001 #include <kernel/proc.h>
1990002 #include <kernel/lib_s.h>
1990003 #include <kernel/lib_k.h>
1990004 #include <errno.h>
1990005 #include <fcntl.h>
1990006 #include <sys/socket.h>
1990007 #include <arpa/inet.h>
1990008 //----------------------------------------------------------
1990009 int
1990010 s_socket (pid_t pid, int family, int type, int protocol)
1990011 {
1990012   fd_t *fd;
1990013   int sfdn;
1990014   file_t *file;
1990015   sock_t *sock;
1990016   // 
1990017   // Check supported family type.
1990018   // 
1990019   if (family != AF_INET)
1990020     {
1990021       errset (EAFNOSUPPORT);
1990022       return (-1);
1990023     }
1990024   // 
1990025   // Check supported communication type.
1990026   // 
1990027   if (type == SOCK_RAW || type == SOCK_DGRAM
1990028       || type == SOCK_STREAM)
1990029     {
1990030       // 
1990031       // Ok.
1990032       // 
1990033       ;
1990034     }
1990035   else
1990036     {
1990037       errset (EPROTONOSUPPORT);
1990038       return (-1);
1990039     }
1990040   // 
1990041   // Check supported protocol type.
1990042   // 
1990043   if (protocol == IPPROTO_ICMP
1990044       || protocol == IPPROTO_UDP || protocol == IPPROTO_TCP)
1990045     {
1990046       // 
1990047       // Ok.
1990048       // 
1990049       ;
1990050     }
1990051   else
1990052     {
1990053       errset (EPROTONOSUPPORT);
1990054       return (-1);
1990055     }
1990056   // 
1990057   // If it is a raw socket, must be a privileged
1990058   // process.
1990059   // 
1990060   if (type == SOCK_RAW && proc_table[pid].euid != 0)
1990061     {
1990062       errset (EACCES);
1990063       return (-1);
1990064     }
1990065   // 
1990066   // Find a free slot inside the sock_table[].
1990067   // 
1990068   sock = sock_reference (-1);
1990069   if (sock == NULL)
1990070     {
1990071       errset (ENFILE);
1990072       return (-1);
1990073     }
1990074   // 
1990075   // Find a free slot inside the file table.
1990076   // 
1990077   file = file_reference (-1);
1990078   if (file == NULL)
1990079     {
1990080       errset (ENFILE);  // Too many files open in
1990081       // system.
1990082       return (-1);
1990083     }
1990084   // 
1990085   // Find a free slot inside the file descriptor
1990086   // table.
1990087   // Variable `sfdn' will be modified by the call to
1990088   // `fd_reference()'.
1990089   // 
1990090   sfdn = -1;
1990091   fd = fd_reference (pid, &sfdn);
1990092   if (fd == NULL)
1990093     {
1990094       errset (EMFILE);  // Too many open files.
1990095       return (-1);
1990096     }
1990097   // 
1990098   // socket, system file and file descriptor ready:
1990099   // reset and put data
1990100   // inside them. Please notice that the
1990101   // tcp.listen_queue[] array is
1990102   // reset with all 0xFF, because zero is a valid file 
1990103   // descriptor
1990104   // number.
1990105   // 
1990106   memset (sock, 0, sizeof (sock_t));
1990107   sock->active = 1;
1990108   sock->family = family;
1990109   sock->type = type;
1990110   sock->protocol = protocol;
1990111   sock->lport = 0;
1990112   sock->laddr = 0;
1990113   sock->rport = 0;
1990114   sock->raddr = 0;
1990115   memset (sock->read.clock, 0x00,
1990116           sizeof (sock->read.clock));
1990117   memset (sock->tcp.listen_queue, 0xFF,
1990118           sizeof (sock->tcp.listen_queue));
1990119   // 
1990120   file->references = 1;
1990121   file->oflags = O_RDWR;
1990122   file->inode = NULL;
1990123   file->sock = sock;
1990124   file->offset = 0;
1990125   // 
1990126   fd->fl_flags = (O_RDWR | O_APPEND);
1990127   fd->fd_flags = 0;
1990128   fd->file = file;
1990129   // 
1990130   // Return the file descriptor.
1990131   // 
1990132   return (sfdn);
1990133 }

94.8.42   kernel/lib_s/s_stat.c

Si veda la sezione 87.55.

2000001 #include <kernel/fs.h>
2000002 #include <errno.h>
2000003 #include <kernel/proc.h>
2000004 #include <kernel/lib_s.h>
2000005 //----------------------------------------------------------
2000006 int
2000007 s_stat (pid_t pid, const char *path, struct stat *buffer)
2000008 {
2000009   proc_t *ps;
2000010   inode_t *inode;
2000011   // 
2000012   // Check path.
2000013   // 
2000014   if (path == NULL || strlen (path) == 0)
2000015     {
2000016       errset (EINVAL);
2000017       return (-1);
2000018     }
2000019   // 
2000020   // Get process.
2000021   // 
2000022   ps = proc_reference (pid);
2000023   // 
2000024   // Try to load the file inode.
2000025   // 
2000026   inode = path_inode (pid, path);
2000027   if (inode == NULL)
2000028     {
2000029       // 
2000030       // Cannot access the file: it does not exists or 
2000031       // permissions are
2000032       // not sufficient. Variable `errno' is set by
2000033       // function
2000034       // `path_inode()'.
2000035       // 
2000036       errset (errno);
2000037       return (-1);
2000038     }
2000039   // 
2000040   // Inode loaded: update the buffer.
2000041   // 
2000042   buffer->st_dev = inode->sb->device;
2000043   buffer->st_ino = inode->ino;
2000044   buffer->st_mode = inode->mode;
2000045   buffer->st_nlink = inode->links;
2000046   buffer->st_uid = inode->uid;
2000047   buffer->st_gid = inode->gid;
2000048   if (S_ISBLK (buffer->st_mode)
2000049       || S_ISCHR (buffer->st_mode))
2000050     {
2000051       buffer->st_rdev = inode->direct[0];
2000052     }
2000053   else
2000054     {
2000055       buffer->st_rdev = 0;
2000056     }
2000057   buffer->st_size = inode->size;
2000058   buffer->st_atime = inode->time;       // All times
2000059   // are the
2000060   // same for
2000061   buffer->st_mtime = inode->time;       // Minix 1
2000062   // file
2000063   // system.
2000064   buffer->st_ctime = inode->time;       // 
2000065   buffer->st_blksize = inode->sb->blksize;
2000066   buffer->st_blocks = inode->blkcnt;
2000067   // 
2000068   // If the inode is a device special file, the
2000069   // `st_rdev' value is
2000070   // taken from the first direct zone (as of Minix 1
2000071   // organization).
2000072   // 
2000073   if (S_ISBLK (inode->mode) || S_ISCHR (inode->mode))
2000074     {
2000075       buffer->st_rdev = inode->direct[0];
2000076     }
2000077   else
2000078     {
2000079       buffer->st_rdev = 0;
2000080     }
2000081   // 
2000082   // Release the inode and return.
2000083   // 
2000084   inode_put (inode);
2000085   // 
2000086   // Return.
2000087   // 
2000088   return (0);
2000089 }

94.8.43   kernel/lib_s/s_stime.c

Si veda la sezione 87.59.

2010001 #include <kernel/lib_s.h>
2010002 #include <kernel/proc.h>
2010003 #include <stddef.h>
2010004 #include <errno.h>
2010005 //----------------------------------------------------------
2010006 extern clock_t _clock_time;     // uint64_t
2010007 //----------------------------------------------------------
2010008 int
2010009 s_stime (pid_t pid, time_t * timer)
2010010 {
2010011   if (proc_table[pid].euid != 0)
2010012     {
2010013       errset (EPERM);
2010014       return (-1);
2010015     }
2010016   // 
2010017   _clock_time = *timer * CLOCKS_PER_SEC;
2010018   return (0);
2010019 }

94.8.44   kernel/lib_s/s_tcgetattr.c

Si veda la sezione 87.58.

2020001 #include <kernel/fs.h>
2020002 #include <errno.h>
2020003 #include <kernel/proc.h>
2020004 #include <kernel/lib_s.h>
2020005 #include <termios.h>
2020006 #include <sys/types.h>
2020007 //----------------------------------------------------------
2020008 int
2020009 s_tcgetattr (pid_t pid, int fdn, struct termios *termios_p)
2020010 {
2020011   file_t *file;
2020012   inode_t *inode;
2020013   dev_t device;
2020014   int t;        // `tty_table[]' subscript.
2020015   int c;        // `c_cc[]' subscript.
2020016   // 
2020017   file = proc_table[pid].fd[fdn].file;
2020018   // 
2020019   if (file == NULL)
2020020     {
2020021       errset (EBADF);
2020022       return (-1);
2020023     }
2020024   // 
2020025   inode = proc_table[pid].fd[fdn].file->inode;
2020026   // 
2020027   if (inode == NULL)
2020028     {
2020029       errset (EBADF);
2020030       return (-1);
2020031     }
2020032   // 
2020033   if (!S_ISCHR (inode->mode))
2020034     {
2020035       errset (ENOTTY);
2020036       return (-1);
2020037     }
2020038   // 
2020039   device = inode->direct[0];
2020040   // 
2020041   if (major (device) != DEV_CONSOLE_MAJOR)
2020042     {
2020043       errset (ENOTTY);
2020044       return (-1);
2020045     }
2020046   // 
2020047   t = minor (device);
2020048   if (t >= TTYS_TOTAL)
2020049     {
2020050       errset (ENOTTY);
2020051       return (-1);
2020052     }
2020053   // 
2020054   // Ok: copy data.
2020055   // 
2020056   termios_p->c_iflag = tty_table[t].attr.c_iflag;
2020057   termios_p->c_oflag = tty_table[t].attr.c_oflag;
2020058   termios_p->c_cflag = tty_table[t].attr.c_cflag;
2020059   termios_p->c_lflag = tty_table[t].attr.c_lflag;
2020060   for (c = 0; c < NCCS; c++)
2020061     {
2020062       termios_p->c_cc[c] = tty_table[t].attr.c_cc[c];
2020063     }
2020064   // 
2020065   // Ok.
2020066   // 
2020067   return (0);
2020068 }

94.8.45   kernel/lib_s/s_tcsetattr.c

Si veda la sezione 87.58.

2030001 #include <kernel/fs.h>
2030002 #include <errno.h>
2030003 #include <kernel/proc.h>
2030004 #include <kernel/lib_s.h>
2030005 #include <termios.h>
2030006 #include <sys/types.h>
2030007 //----------------------------------------------------------
2030008 // The following are masks of the implemented
2030009 // attributes.
2030010 //
2030011 #define MASK_C_IFLAG (BRKINT|ICRNL|IGNBRK|IGNCR)
2030012 #define MASK_C_OFLAG 0
2030013 #define MASK_C_CFLAG 0
2030014 #define MASK_C_LFLAG \
2030015     (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG)
2030016 //----------------------------------------------------------
2030017 int
2030018 s_tcsetattr (pid_t pid, int fdn, int action,
2030019              struct termios *termios_p)
2030020 {
2030021   file_t *file;
2030022   inode_t *inode;
2030023   dev_t device;
2030024   int t;        // `tty_table[]' subscript.
2030025   int c;        // `c_cc[]' subscript.
2030026   // 
2030027   file = proc_table[pid].fd[fdn].file;
2030028   // 
2030029   if (file == NULL)
2030030     {
2030031       errset (EBADF);
2030032       return (-1);
2030033     }
2030034   // 
2030035   inode = proc_table[pid].fd[fdn].file->inode;
2030036   // 
2030037   if (inode == NULL)
2030038     {
2030039       errset (EBADF);
2030040       return (-1);
2030041     }
2030042   // 
2030043   if (!S_ISCHR (inode->mode))
2030044     {
2030045       errset (ENOTTY);
2030046       return (-1);
2030047     }
2030048   // 
2030049   device = inode->direct[0];
2030050   // 
2030051   if (major (device) != DEV_CONSOLE_MAJOR)
2030052     {
2030053       errset (ENOTTY);
2030054       return (-1);
2030055     }
2030056   // 
2030057   t = minor (device);
2030058   if (t >= TTYS_TOTAL)
2030059     {
2030060       errset (ENOTTY);
2030061       return (-1);
2030062     }
2030063   // 
2030064   // The parameter `actions' is silently ignored: only 
2030065   // immediate update will take place.
2030066   // 
2030067   // The function will not notice if at least a
2030068   // successful attribute change is done, so,
2030069   // after this point, the return value is
2030070   // always zero.
2030071   // 
2030072   tty_table[t].attr.c_iflag =
2030073     (termios_p->c_iflag & MASK_C_IFLAG);
2030074   tty_table[t].attr.c_oflag =
2030075     (termios_p->c_oflag & MASK_C_OFLAG);
2030076   tty_table[t].attr.c_cflag =
2030077     (termios_p->c_cflag & MASK_C_CFLAG);
2030078   tty_table[t].attr.c_lflag =
2030079     (termios_p->c_lflag & MASK_C_LFLAG);
2030080   for (c = 0; c < NCCS; c++)
2030081     {
2030082       // 
2030083       // Should be done some check here?
2030084       // 
2030085       tty_table[t].attr.c_cc[c] = termios_p->c_cc[c];
2030086     }
2030087   // 
2030088   // Ok.
2030089   // 
2030090   return (0);
2030091 }

94.8.46   kernel/lib_s/s_time.c

Si veda la sezione 87.59.

2040001 #include <kernel/lib_k.h>
2040002 #include <kernel/lib_s.h>
2040003 #include <stddef.h>
2040004 //----------------------------------------------------------
2040005 extern clock_t _clock_time;     // uint64_t
2040006 //----------------------------------------------------------
2040007 time_t
2040008 s_time (pid_t pid, time_t * timer)
2040009 {
2040010   time_t time = _clock_time / CLOCKS_PER_SEC;
2040011   if (timer != NULL)
2040012     {
2040013       *timer = time;
2040014     }
2040015   return (time);
2040016 }

94.8.47   kernel/lib_s/s_umount.c

Si veda la sezione 87.36.

2050001 #include <kernel/fs.h>
2050002 #include <errno.h>
2050003 #include <kernel/proc.h>
2050004 #include <kernel/lib_s.h>
2050005 //----------------------------------------------------------
2050006 int
2050007 s_umount (pid_t pid, const char *path_mnt)
2050008 {
2050009   proc_t *ps;
2050010   dev_t device; // Device to mount.
2050011   inode_t *inode_mount_point;   // Original mount
2050012   // point.
2050013   inode_t *inode;       // Inode table.
2050014   int i;        // Inode table index.
2050015   // 
2050016   // Get process.
2050017   // 
2050018   ps = proc_reference (pid);
2050019   // 
2050020   // Verify to be the super user.
2050021   // 
2050022   if (ps->euid != 0)
2050023     {
2050024       errset (EPERM);   // Operation not permitted.
2050025       return (-1);
2050026     }
2050027   // 
2050028   // Get the directory mount point.
2050029   // 
2050030   inode_mount_point = path_inode (pid, path_mnt);
2050031   if (inode_mount_point == NULL)
2050032     {
2050033       errset (ENOENT);  // No such file or directory.
2050034       return (-1);
2050035     }
2050036   // 
2050037   // Verify that the path is a directory.
2050038   // 
2050039   if (!S_ISDIR (inode_mount_point->mode))
2050040     {
2050041       inode_put (inode_mount_point);
2050042       errset (ENOTDIR); // Not a directory.
2050043       return (-1);
2050044     }
2050045   // 
2050046   // Verify that there is something attached.
2050047   // 
2050048   device = inode_mount_point->sb_attached->device;
2050049   if (device == 0)
2050050     {
2050051       // 
2050052       // There is nothing to unmount.
2050053       // 
2050054       inode_put (inode_mount_point);
2050055       errset (E_NOT_MOUNTED);   // Not mounted.
2050056       return (-1);
2050057     }
2050058   // 
2050059   // Are there exactly two internal references? Let's
2050060   // explain:
2050061   // the directory that act as mount point, should
2050062   // have one reference
2050063   // because it is mounting something and another
2050064   // because it was just
2050065   // opened again, a few lines above. If there are
2050066   // more references
2050067   // it is wrong; if there are less, it is also wrong
2050068   // at this point.
2050069   // 
2050070   if (inode_mount_point->references != 2)
2050071     {
2050072       inode_put (inode_mount_point);
2050073       errset (EUNKNOWN);        // Unknown error.
2050074       return (-1);
2050075     }
2050076   // 
2050077   // All data is available: find if there are open
2050078   // file inside
2050079   // the file system to unmount. But first load the
2050080   // inode table
2050081   // pointer.
2050082   // 
2050083   inode = inode_reference ((dev_t) 0, (ino_t) 0);
2050084   if (inode == NULL)
2050085     {
2050086       // 
2050087       // This error should not happen.
2050088       // 
2050089       inode_put (inode_mount_point);
2050090       errset (EUNKNOWN);        // Unknown error.
2050091       return (-1);
2050092     }
2050093   // 
2050094   // Scan the inode table.
2050095   // 
2050096   for (i = 0; i < INODE_MAX_SLOTS; i++)
2050097     {
2050098       if ((inode[i].sb ==
2050099            inode_mount_point->sb_attached)
2050100           && (inode[i].references > 0))
2050101         {
2050102           // 
2050103           // At least one file is open inside the
2050104           // super block to
2050105           // release: cannot unmount.
2050106           // 
2050107           inode_put (inode_mount_point);
2050108           errset (EBUSY);       // Device or resource
2050109           // busy.
2050110           return (-1);
2050111         }
2050112     }
2050113   // 
2050114   // Can unmount: save and remove the super block
2050115   // memory;
2050116   // clear the mount point reference and put inode.
2050117   // 
2050118   inode_mount_point->sb_attached->changed = 1;
2050119   sb_save (inode_mount_point->sb_attached);
2050120   // 
2050121   inode_mount_point->sb_attached->device = 0;
2050122   inode_mount_point->sb_attached->inode_mounted_on = NULL;
2050123   inode_mount_point->sb_attached->blksize = 0;
2050124   inode_mount_point->sb_attached->options = 0;
2050125   // 
2050126   inode_mount_point->sb_attached = NULL;
2050127   inode_mount_point->references = 0;
2050128   inode_put (inode_mount_point);
2050129   // 
2050130   inode_put (inode_mount_point);
2050131   // 
2050132   return (0);
2050133 }

94.8.48   kernel/lib_s/s_unlink.c

Si veda la sezione 87.62.

2060001 #include <kernel/fs.h>
2060002 #include <errno.h>
2060003 #include <kernel/proc.h>
2060004 #include <libgen.h>
2060005 #include <kernel/lib_s.h>
2060006 #include <kernel/lib_k.h>
2060007 //----------------------------------------------------------
2060008 int
2060009 s_unlink (pid_t pid, const char *path)
2060010 {
2060011   proc_t *ps;
2060012   inode_t *inode_unlink;
2060013   inode_t *inode_directory;
2060014   char path_unlink[PATH_MAX];
2060015   char path_copy[PATH_MAX];
2060016   char *path_directory;
2060017   char *name_unlink;
2060018   dev_t device;
2060019   off_t start;
2060020   char buffer[SB_MAX_ZONE_SIZE];
2060021   directory_t *dir = (directory_t *) buffer;
2060022   int status;
2060023   ssize_t size_read;
2060024   ssize_t size_written;
2060025   int d;        // Directory buffer index.
2060026   // 
2060027   // Get process.
2060028   // 
2060029   ps = proc_reference (pid);
2060030   // 
2060031   // Get full paths.
2060032   // 
2060033   path_full (path, ps->path_cwd, path_unlink);
2060034   strncpy (path_copy, path_unlink, PATH_MAX);
2060035   path_directory = dirname (path_copy);
2060036   // 
2060037   // Get the inode to be unlinked.
2060038   // 
2060039   inode_unlink = path_inode (pid, path_unlink);
2060040   if (inode_unlink == NULL)
2060041     {
2060042       return (-1);
2060043     }
2060044   // 
2060045   // If it is a directory, verify that it is empty.
2060046   // 
2060047   if (S_ISDIR (inode_unlink->mode))
2060048     {
2060049       if (!inode_dir_empty (inode_unlink))
2060050         {
2060051           inode_put (inode_unlink);
2060052           errset (ENOTEMPTY);   // Directory not
2060053           // empty.
2060054           return (-1);
2060055         }
2060056     }
2060057   // 
2060058   // Get the inode of the directory containing it.
2060059   // 
2060060   inode_directory = path_inode (pid, path_directory);
2060061   if (inode_directory == NULL)
2060062     {
2060063       inode_put (inode_unlink);
2060064       return (-1);
2060065     }
2060066   // 
2060067   // Check if something is mounted on the directory.
2060068   // 
2060069   if (inode_directory->sb_attached != NULL)
2060070     {
2060071       // 
2060072       // Must select the right directory.
2060073       // 
2060074       device = inode_directory->sb_attached->device;
2060075       inode_put (inode_directory);
2060076       inode_directory = inode_get (device, 1);
2060077       if (inode_directory == NULL)
2060078         {
2060079           inode_put (inode_unlink);
2060080           return (-1);
2060081         }
2060082     }
2060083   // 
2060084   // Check if write is allowed for the file system.
2060085   // 
2060086   if (inode_directory->sb->options & MOUNT_RO)
2060087     {
2060088       errset (EROFS);   // Read-only file system.
2060089       return (-1);
2060090     }
2060091   // 
2060092   // Verify access permissions for the directory. The
2060093   // number "3" means
2060094   // that the user must have access permission and
2060095   // write permission:
2060096   // "-wx" == 2+1 == 3.
2060097   // 
2060098   status = inode_check (inode_directory, S_IFDIR, 3,
2060099                         ps->euid, ps->egid);
2060100   if (status != 0)
2060101     {
2060102       errset (EPERM);   // Operation not permitted.
2060103