You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(35) |
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(37) |
Feb
(10) |
Mar
|
Apr
(2) |
May
(17) |
Jun
(1) |
Jul
(14) |
Aug
(14) |
Sep
(4) |
Oct
|
Nov
(14) |
Dec
(4) |
2005 |
Jan
(6) |
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(92) |
Dec
(12) |
2006 |
Jan
(3) |
Feb
(4) |
Mar
|
Apr
(5) |
May
(3) |
Jun
(15) |
Jul
(3) |
Aug
(1) |
Sep
(29) |
Oct
(1) |
Nov
(6) |
Dec
(5) |
2007 |
Jan
(2) |
Feb
(2) |
Mar
|
Apr
(3) |
May
(14) |
Jun
(2) |
Jul
(16) |
Aug
(73) |
Sep
(12) |
Oct
(9) |
Nov
(27) |
Dec
(3) |
2008 |
Jan
(4) |
Feb
(4) |
Mar
(3) |
Apr
(8) |
May
(23) |
Jun
(4) |
Jul
(1) |
Aug
(3) |
Sep
(7) |
Oct
(5) |
Nov
(1) |
Dec
(1) |
2009 |
Jan
|
Feb
(10) |
Mar
|
Apr
(4) |
May
(4) |
Jun
(10) |
Jul
|
Aug
(1) |
Sep
|
Oct
(7) |
Nov
|
Dec
(1) |
2010 |
Jan
|
Feb
(1) |
Mar
|
Apr
(6) |
May
|
Jun
(3) |
Jul
(11) |
Aug
(1) |
Sep
|
Oct
(15) |
Nov
(1) |
Dec
(5) |
2011 |
Jan
(4) |
Feb
(1) |
Mar
(6) |
Apr
|
May
(22) |
Jun
|
Jul
(8) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
2012 |
Jan
|
Feb
(10) |
Mar
(1) |
Apr
(6) |
May
(27) |
Jun
(48) |
Jul
(30) |
Aug
(4) |
Sep
|
Oct
(3) |
Nov
(1) |
Dec
(11) |
2013 |
Jan
(4) |
Feb
(7) |
Mar
(6) |
Apr
(18) |
May
(28) |
Jun
(20) |
Jul
|
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
(2) |
Dec
(7) |
2014 |
Jan
(3) |
Feb
(2) |
Mar
(4) |
Apr
(9) |
May
(11) |
Jun
(10) |
Jul
|
Aug
(18) |
Sep
(12) |
Oct
(17) |
Nov
(10) |
Dec
(16) |
2015 |
Jan
(5) |
Feb
(1) |
Mar
(5) |
Apr
(4) |
May
(28) |
Jun
(2) |
Jul
|
Aug
|
Sep
(6) |
Oct
|
Nov
(2) |
Dec
(1) |
2016 |
Jan
(14) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
(3) |
Jul
(4) |
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
|
Dec
(1) |
2017 |
Jan
(11) |
Feb
|
Mar
(21) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(2) |
Sep
(4) |
Oct
(4) |
Nov
|
Dec
(1) |
2019 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(13) |
Sep
(4) |
Oct
|
Nov
|
Dec
|
2020 |
Jan
(10) |
Feb
(9) |
Mar
(5) |
Apr
(4) |
May
(3) |
Jun
(18) |
Jul
(4) |
Aug
(2) |
Sep
(20) |
Oct
(2) |
Nov
|
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(1) |
Jun
(2) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
2022 |
Jan
(1) |
Feb
(2) |
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
|
Oct
(1) |
Nov
|
Dec
(1) |
2023 |
Jan
(10) |
Feb
(7) |
Mar
(29) |
Apr
(31) |
May
(29) |
Jun
(34) |
Jul
(3) |
Aug
(24) |
Sep
(22) |
Oct
(10) |
Nov
(38) |
Dec
(27) |
2024 |
Jan
(15) |
Feb
(8) |
Mar
(4) |
Apr
(20) |
May
(33) |
Jun
(18) |
Jul
(15) |
Aug
(23) |
Sep
(26) |
Oct
(32) |
Nov
(6) |
Dec
(4) |
2025 |
Jan
(7) |
Feb
(1) |
Mar
(1) |
Apr
(4) |
May
(46) |
Jun
(19) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ljs...@us...> - 2010-10-30 20:50:54
|
Revision: 692 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=692&view=rev Author: ljsebald Date: 2010-10-30 20:50:48 +0000 (Sat, 30 Oct 2010) Log Message: ----------- Adding in code to do MD5 checksums to libkosutils. A bit random, but I did originally write this for something that was for KOS... Modified Paths: -------------- kos/addons/libkosutils/Makefile Added Paths: ----------- kos/addons/include/kos/md5.h kos/addons/libkosutils/md5.c Added: kos/addons/include/kos/md5.h =================================================================== --- kos/addons/include/kos/md5.h (rev 0) +++ kos/addons/include/kos/md5.h 2010-10-30 20:50:48 UTC (rev 692) @@ -0,0 +1,27 @@ +/* KallistiOS ##version## + + kos/md5.h + Copyright (C) 2010 Lawrence Sebald +*/ + +#ifndef __KOS_MD5_H +#define __KOS_MD5_H + +#include <sys/cdefs.h> +__BEGIN_DECLS + +#include <arch/types.h> + +typedef struct kos_md5_cxt { + uint64 size; + uint32 hash[4]; + uint8 buf[64]; +} kos_md5_cxt_t; + +void kos_md5_start(kos_md5_cxt_t *cxt); +void kos_md5_hash_block(kos_md5_cxt_t *cxt, const uint8 *input, uint32 size); +void kos_md5_finish(kos_md5_cxt_t *cxt, uint8 output[16]); + +__END_DECLS + +#endif /* !__KOS_MD5_H */ Modified: kos/addons/libkosutils/Makefile =================================================================== --- kos/addons/libkosutils/Makefile 2010-10-25 17:55:48 UTC (rev 691) +++ kos/addons/libkosutils/Makefile 2010-10-30 20:50:48 UTC (rev 692) @@ -2,6 +2,6 @@ # TARGET = libkosutils.a -OBJS = bspline.o img.o pcx_small.o +OBJS = bspline.o img.o pcx_small.o md5.o include $(KOS_BASE)/addons/Makefile.prefab Added: kos/addons/libkosutils/md5.c =================================================================== --- kos/addons/libkosutils/md5.c (rev 0) +++ kos/addons/libkosutils/md5.c 2010-10-30 20:50:48 UTC (rev 692) @@ -0,0 +1,274 @@ +/* KallistiOS ##version## + + md5.c + Copyright (C) 2010 Lawrence Sebald +*/ + +#include <string.h> +#include <arch/types.h> + +#include <kos/md5.h> + +/* Initial values used in starting the MD5 checksum */ +static const uint32 md5initial[4] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 +}; + +/* We will append somewhere between 1 and 64 bytes of padding to every message, + depending on its length. This is the padding that is to be used. */ +static const uint8 md5padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* MD5 "magic" values */ +static const uint32 md5tab[64] = { + 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 +}; + +/* Code to generate the above table (in case anyone is interested): + +#include <stdio.h> +#include <math.h> + +int main(int argc, char *argv[]) { + int i; + double tmp; + + printf("static const uint32 md5tab[64] = {"); + + for(i = 0; i < 64; ++i) { + if((i % 4) == 0) + printf("\n "); + + tmp = sin(i + 1) * 4294967296.0; + if(tmp < 0) + tmp = -tmp; + + printf(" 0x%08X", (unsigned long) tmp); + + if(i == 63) + break; + + printf(","); + } + + printf("\n};\n"); + return 0; +} +*/ + +#define MD5_PAD_LEN(mod) (((mod) < 56) ? 56 - (mod) : 120 - (mod)) + +#define MD5_ROT(x, y) ((x << y) | ((x & 0xFFFFFFFF) >> (32 - y))) + +/* Basic MD5 functions */ +#define MD5_F(x, y, z) (z ^ (x & (y ^ z))) +#define MD5_G(x, y, z) (y ^ (z & (x ^ y))) +#define MD5_H(x, y, z) (x ^ y ^ z) +#define MD5_I(x, y, z) (y ^ (x | (~z))) + +/* Compound operations, consisting of a F, G, H, or I operation and a rotate */ +#define MD5_FH(a, b, c, d, w, s, t) { \ + (a) += MD5_F((b), (c), (d)) + (w) + (t); \ + (a) = MD5_ROT((a), (s)); \ + (a) += (b); \ +} + +#define MD5_GH(a, b, c, d, w, s, t) { \ + (a) += MD5_G((b), (c), (d)) + (w) + (t); \ + (a) = MD5_ROT((a), (s)); \ + (a) += (b); \ +} + +#define MD5_HH(a, b, c, d, w, s, t) { \ + (a) += MD5_H((b), (c), (d)) + (w) + (t); \ + (a) = MD5_ROT((a), (s)); \ + (a) += (b); \ +} + +#define MD5_IH(a, b, c, d, w, s, t) { \ + (a) += MD5_I((b), (c), (d)) + (w) + (t); \ + (a) = MD5_ROT((a), (s)); \ + (a) += (b); \ +} + +void kos_md5_start(kos_md5_cxt_t *cxt) { + cxt->size = 0; + cxt->hash[0] = md5initial[0]; + cxt->hash[1] = md5initial[1]; + cxt->hash[2] = md5initial[2]; + cxt->hash[3] = md5initial[3]; +} + +/* input must be at least 64 bytes long */ +static void kos_md5_process(kos_md5_cxt_t *cxt, const uint8 *input) { + uint32 a, b, c, d, w[16]; + int i; + + /* Read in what we're starting with */ + a = cxt->hash[0]; + b = cxt->hash[1]; + c = cxt->hash[2]; + d = cxt->hash[3]; + + /* Read the input into our buffer */ + for(i = 0; i < 16; ++i) { + w[i] = input[(i << 2)] | (input[(i << 2) + 1] << 8) | + (input[(i << 2) + 2] << 16) | (input[(i << 2) + 3] << 24); + } + + /* First Round */ + MD5_FH(a, b, c, d, w[ 0], 7, md5tab[ 0]); + MD5_FH(d, a, b, c, w[ 1], 12, md5tab[ 1]); + MD5_FH(c, d, a, b, w[ 2], 17, md5tab[ 2]); + MD5_FH(b, c, d, a, w[ 3], 22, md5tab[ 3]); + MD5_FH(a, b, c, d, w[ 4], 7, md5tab[ 4]); + MD5_FH(d, a, b, c, w[ 5], 12, md5tab[ 5]); + MD5_FH(c, d, a, b, w[ 6], 17, md5tab[ 6]); + MD5_FH(b, c, d, a, w[ 7], 22, md5tab[ 7]); + MD5_FH(a, b, c, d, w[ 8], 7, md5tab[ 8]); + MD5_FH(d, a, b, c, w[ 9], 12, md5tab[ 9]); + MD5_FH(c, d, a, b, w[10], 17, md5tab[10]); + MD5_FH(b, c, d, a, w[11], 22, md5tab[11]); + MD5_FH(a, b, c, d, w[12], 7, md5tab[12]); + MD5_FH(d, a, b, c, w[13], 12, md5tab[13]); + MD5_FH(c, d, a, b, w[14], 17, md5tab[14]); + MD5_FH(b, c, d, a, w[15], 22, md5tab[15]); + + /* Second Round */ + MD5_GH(a, b, c, d, w[ 1], 5, md5tab[16]); + MD5_GH(d, a, b, c, w[ 6], 9, md5tab[17]); + MD5_GH(c, d, a, b, w[11], 14, md5tab[18]); + MD5_GH(b, c, d, a, w[ 0], 20, md5tab[19]); + MD5_GH(a, b, c, d, w[ 5], 5, md5tab[20]); + MD5_GH(d, a, b, c, w[10], 9, md5tab[21]); + MD5_GH(c, d, a, b, w[15], 14, md5tab[22]); + MD5_GH(b, c, d, a, w[ 4], 20, md5tab[23]); + MD5_GH(a, b, c, d, w[ 9], 5, md5tab[24]); + MD5_GH(d, a, b, c, w[14], 9, md5tab[25]); + MD5_GH(c, d, a, b, w[ 3], 14, md5tab[26]); + MD5_GH(b, c, d, a, w[ 8], 20, md5tab[27]); + MD5_GH(a, b, c, d, w[13], 5, md5tab[28]); + MD5_GH(d, a, b, c, w[ 2], 9, md5tab[29]); + MD5_GH(c, d, a, b, w[ 7], 14, md5tab[30]); + MD5_GH(b, c, d, a, w[12], 20, md5tab[31]); + + /* Third Round */ + MD5_HH(a, b, c, d, w[ 5], 4, md5tab[32]); + MD5_HH(d, a, b, c, w[ 8], 11, md5tab[33]); + MD5_HH(c, d, a, b, w[11], 16, md5tab[34]); + MD5_HH(b, c, d, a, w[14], 23, md5tab[35]); + MD5_HH(a, b, c, d, w[ 1], 4, md5tab[36]); + MD5_HH(d, a, b, c, w[ 4], 11, md5tab[37]); + MD5_HH(c, d, a, b, w[ 7], 16, md5tab[38]); + MD5_HH(b, c, d, a, w[10], 23, md5tab[39]); + MD5_HH(a, b, c, d, w[13], 4, md5tab[40]); + MD5_HH(d, a, b, c, w[ 0], 11, md5tab[41]); + MD5_HH(c, d, a, b, w[ 3], 16, md5tab[42]); + MD5_HH(b, c, d, a, w[ 6], 23, md5tab[43]); + MD5_HH(a, b, c, d, w[ 9], 4, md5tab[44]); + MD5_HH(d, a, b, c, w[12], 11, md5tab[45]); + MD5_HH(c, d, a, b, w[15], 16, md5tab[46]); + MD5_HH(b, c, d, a, w[ 2], 23, md5tab[47]); + + /* Last Round */ + MD5_IH(a, b, c, d, w[ 0], 6, md5tab[48]); + MD5_IH(d, a, b, c, w[ 7], 10, md5tab[49]); + MD5_IH(c, d, a, b, w[14], 15, md5tab[50]); + MD5_IH(b, c, d, a, w[ 5], 21, md5tab[51]); + MD5_IH(a, b, c, d, w[12], 6, md5tab[52]); + MD5_IH(d, a, b, c, w[ 3], 10, md5tab[53]); + MD5_IH(c, d, a, b, w[10], 15, md5tab[54]); + MD5_IH(b, c, d, a, w[ 1], 21, md5tab[55]); + MD5_IH(a, b, c, d, w[ 8], 6, md5tab[56]); + MD5_IH(d, a, b, c, w[15], 10, md5tab[57]); + MD5_IH(c, d, a, b, w[ 6], 15, md5tab[58]); + MD5_IH(b, c, d, a, w[13], 21, md5tab[59]); + MD5_IH(a, b, c, d, w[ 4], 6, md5tab[60]); + MD5_IH(d, a, b, c, w[11], 10, md5tab[61]); + MD5_IH(c, d, a, b, w[ 2], 15, md5tab[62]); + MD5_IH(b, c, d, a, w[ 9], 21, md5tab[63]); + + /* Save out what we have */ + cxt->hash[0] += a; + cxt->hash[1] += b; + cxt->hash[2] += c; + cxt->hash[3] += d; +} + +void kos_md5_hash_block(kos_md5_cxt_t *cxt, const uint8 *input, uint32 size) { + uint32 left, copy; + + /* Figure out what we had left over from last time (if anything) */ + left = (uint32)((cxt->size >> 3) & 0x3F); + copy = 64 - left; + + /* Update the size */ + cxt->size += (size << 3); + + /* Deal with what was left over, if we have enough data to do so */ + if(left && size >= copy) { + memcpy(&cxt->buf[left], input, copy); + kos_md5_process(cxt, cxt->buf); + left = 0; + size -= copy; + input += copy; + } + + /* Hash each block of the data */ + while(size >= 64) { + kos_md5_process(cxt, input); + input += 64; + size -= 64; + } + + /* Buffer anything left over */ + if(size) { + memcpy(&cxt->buf[left], input, size); + } +} + +void kos_md5_finish(kos_md5_cxt_t *cxt, uint8 output[16]) { + uint64 len = cxt->size; + uint32 blen = (cxt->size >> 3) & 0x3F; + uint32 plen = MD5_PAD_LEN(blen); + int i; + uint8 len_bytes[8]; + + /* Add in the padding */ + kos_md5_hash_block(cxt, md5padding, plen); + + /* Hash in the length -- this will finish the last 64-byte block */ + len_bytes[0] = (uint8)(len); + len_bytes[1] = (uint8)(len >> 8); + len_bytes[2] = (uint8)(len >> 16); + len_bytes[3] = (uint8)(len >> 24); + len_bytes[4] = (uint8)(len >> 32); + len_bytes[5] = (uint8)(len >> 40); + len_bytes[6] = (uint8)(len >> 48); + len_bytes[7] = (uint8)(len >> 56); + kos_md5_hash_block(cxt, len_bytes, 8); + + /* Copy out the hash, since we're done */ + for(i = 0; i < 16; ++i) { + output[i] = (uint8)(cxt->hash[i >> 2] >> ((i & 0x03) << 3)); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-25 17:55:54
|
Revision: 691 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=691&view=rev Author: ljsebald Date: 2010-10-25 17:55:48 +0000 (Mon, 25 Oct 2010) Log Message: ----------- Add doxygen comments to the modem driver headers. Modified Paths: -------------- kos/kernel/arch/dreamcast/include/dc/modem/mconst.h kos/kernel/arch/dreamcast/include/dc/modem/modem.h Modified: kos/kernel/arch/dreamcast/include/dc/modem/mconst.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/modem/mconst.h 2010-10-25 17:55:16 UTC (rev 690) +++ kos/kernel/arch/dreamcast/include/dc/modem/mconst.h 2010-10-25 17:55:48 UTC (rev 691) @@ -7,6 +7,19 @@ */ +/** \file dc/modem/mconst.h + \brief Constants used in the modem driver. + + This file contains constants that are used for the modem driver. You should + not ever need to include this file directly, as the main modem driver header + file includes it automatically. + + Generally, you will not need to use the stuff in this file yourself at all, + as the main modem header file defines many useful combinations for you. + + \author Nick Kochakian +*/ + /* Modem constants are defined here. Automatically included by modem.h */ #ifndef __MODEM_MCONST_H #define __MODEM_MCONST_H @@ -19,7 +32,18 @@ something very bad to happen. Only use the MODEM_SPEED_* constants defined in modem.h! */ -/* Speeds */ +/** \defgroup modem_speeds Modem speed values + + This group defines the available speed values that are able to be used with + the Dreamcast's modem. The actual speed value consists of one of these in + the lower 4 bits and one of the protocols in the upper 4 bits. Don't try to + use any speeds not defined here, as bad things may happen. + + It should be fairly obvious from the names what the speeds are (they're all + expressed in bits per second). + + @{ +*/ #define MODEM_SPEED_AUTO 0x0 #define MODEM_SPEED_1200 0x0 #define MODEM_SPEED_2400 0x1 @@ -36,8 +60,20 @@ #define MODEM_SPEED_28000 0xC #define MODEM_SPEED_31200 0xD #define MODEM_SPEED_33600 0xE +/** @} */ -/* Protocols */ +/** \defgroup modem_protocols Modem protocol values + + This group defines the available protocol values that are able to be used + with the Dreamcast's modem. The actual speed value consists of one of these + in the upper 4 bits and one of the speeds in the lower 4 bits. Don't try to + use any protocols not defined here, as bad things may happen. + + It should be fairly obvious from the names what the protocols that will be + used are. + + @{ +*/ #define MODEM_PROTOCOL_V17 0x0 #define MODEM_PROTOCOL_V22 0x1 #define MODEM_PROTOCOL_V22BIS 0x2 @@ -45,11 +81,32 @@ #define MODEM_PROTOCOL_V32BIS 0x4 #define MODEM_PROTOCOL_V34 0x5 #define MODEM_PROTOCOL_V8 0x6 +/** @} */ +/** \brief Extract the protocol from a full speed/protocol value. + \param x The speed/protocol value to look at. + \return The protocol in use. + \see modem_protocols +*/ #define MODEM_SPEED_GET_PROTOCOL(x) ((modem_speed_t)(x) >> 4) + +/** \brief Extract the speed from a full speed/protocol value. + \param x The speed/protocol value to look at. + \return The speed in use. + \see modem_speeds +*/ #define MODEM_SPEED_GET_SPEED(x) ((modem_speed_t)(x) & 0xF) + +/** \brief Combine a protocol and speed into a single value. + \param p The protocol to use. + \param s The speed to use. + \return The full speed/protocol value. + \see modem_protocols + \see modem_speeds +*/ #define MODEM_MAKE_SPEED(p, s) ((modem_speed_t)((((p) & 0xF) << 4) | ((s) & 0xF))) +/** \brief Modem speed/protocol value type. */ typedef unsigned char modem_speed_t; #endif Modified: kos/kernel/arch/dreamcast/include/dc/modem/modem.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/modem/modem.h 2010-10-25 17:55:16 UTC (rev 690) +++ kos/kernel/arch/dreamcast/include/dc/modem/modem.h 2010-10-25 17:55:48 UTC (rev 691) @@ -7,77 +7,254 @@ */ +/** \file dc/modem/modem.h + \brief Definitions to use the Dreamcast modem. + + This file contains functions and constants to be used with the Dreamcast + modem driver. + + \author Nick Kochakian +*/ + #ifndef __DC_MODEM_MODEM_H #define __DC_MODEM_MODEM_H #include "mconst.h" -#define MODEM_MODE_REMOTE 0 /* Connect to a remote modem */ -#define MODEM_MODE_ANSWER 1 /* Answer a call when a ring is detected */ -#define MODEM_MODE_NULL 255 /* Not doing anything. Don't give this to - any function! */ +/** \defgroup modem_modes Modes of operation of the Dreamcast modem. -/* V.22 bis modes */ + This group defines the modes that the Dreamcast modem can be in at any given + point in time. + + @{ +*/ +/** \brief Connect to a remote modem. */ +#define MODEM_MODE_REMOTE 0 + +/** \brief Answer a call when a ring is detected. */ +#define MODEM_MODE_ANSWER 1 + +/** \brief Modem not in use. Do not attempt to set this mode yourself! */ +#define MODEM_MODE_NULL 255 +/** @} */ + +/** \defgroup modem_v22bis Modem V.22bis modes + @{ +*/ +/** \brief 1200bps, V.22bis */ #define MODEM_SPEED_V22BIS_1200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22BIS, MODEM_SPEED_1200) + +/** \brief 2400bps, V.22bis */ #define MODEM_SPEED_V22BIS_2400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22BIS, MODEM_SPEED_2400) +/** @} */ -/* V.22 modes */ +/** \defgroup modem_v22 Modem V.22 modes + @{ +*/ +/** \brief 1200bps, V.22 */ #define MODEM_SPEED_V22_1200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V22, MODEM_SPEED_1200) +/** @} */ -/* V.32 modes */ +/** \defgroup modem_v32 Modem V.32 modes + @{ +*/ +/** \brief 4800bps, V.32 */ #define MODEM_SPEED_V32_4800 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32, MODEM_SPEED_4800) + +/** \brief 9600bps, V.32 */ #define MODEM_SPEED_V32_9600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32, MODEM_SPEED_9600) +/** @} */ -/* V.32 bis modes */ +/** \defgroup modem_v32bis Modem V.32 bis modes + @{ +*/ +/** \brief 7200bps, V.32bis */ #define MODEM_SPEED_V32BIS_7200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_7200) + +/** \brief 12000bps, V.32bis */ #define MODEM_SPEED_V32BIS_12000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_12000) + +/** \brief 14400bps, V.32bis */ #define MODEM_SPEED_V32BIS_14400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V32BIS, MODEM_SPEED_14400) +/** @} */ -/* V.8 modes */ +/** \defgroup modem_v8 Modem V.8 modes + @{ +*/ +/** \brief 2400bps, V.8 */ #define MODEM_SPEED_V8_2400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_2400) + +/** \brief 4800bps, V.8 */ #define MODEM_SPEED_V8_4800 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_4800) + +/** \brief 7200bps, V.8 */ #define MODEM_SPEED_V8_7200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_7200) + +/** \brief 9600bps, V.8 */ #define MODEM_SPEED_V8_9600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_9600) + +/** \brief 12000bps, V.8 */ #define MODEM_SPEED_V8_12000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_12000) + +/** \brief 14400bps, V.8 */ #define MODEM_SPEED_V8_14400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_14400) + +/** \brief 16800bps, V.8 */ #define MODEM_SPEED_V8_16800 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_16800) + +/** \brief 19200bps, V.8 */ #define MODEM_SPEED_V8_19200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_19200) + +/** \brief 21600bps, V.8 */ #define MODEM_SPEED_V8_21600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_21600) + +/** \brief 24000bps, V.8 */ #define MODEM_SPEED_V8_24000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_24000) + +/** \brief 26400bps, V.8 */ #define MODEM_SPEED_V8_26400 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_26400) + +/** \brief 28000bps, V.8 */ #define MODEM_SPEED_V8_28000 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_28000) + +/** \brief 31200bps, V.8 */ #define MODEM_SPEED_V8_31200 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_31200) + +/** \brief 33600bps, V.8 */ #define MODEM_SPEED_V8_33600 MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_33600) + +/** \brief Automatically set speed, V.8 */ #define MODEM_SPEED_V8_AUTO MODEM_MAKE_SPEED(MODEM_PROTOCOL_V8, MODEM_SPEED_1200) +/** @} */ -/* Event constants */ +/** \brief Modem event types. + + These are teh events that a modem event handler should be expected to + receive at any given point in time. +*/ typedef enum { - MODEM_EVENT_CONNECTION_FAILED = 0, /* The modem tried to establish a connection but failed */ - MODEM_EVENT_CONNECTED, /* A connection has been established */ - MODEM_EVENT_DISCONNECTED, /* The remote modem dropped the connection */ - MODEM_EVENT_RX_NOT_EMPTY, /* New data has entered the previously empty receive buffer */ - MODEM_EVENT_OVERFLOW, /* The receive buffer overflowed and was cleared */ - MODEM_EVENT_TX_EMPTY /* The transmission buffer has been emptied */ + /** \brief The modem tried to establish a connection, but failed.*/ + MODEM_EVENT_CONNECTION_FAILED = 0, + + /** \brief A connection has been established. */ + MODEM_EVENT_CONNECTED, + + /** \brief The remote modem dropped the connection. */ + MODEM_EVENT_DISCONNECTED, + + /** \brief New data has entered the previously empty receive buffer. */ + MODEM_EVENT_RX_NOT_EMPTY, + + /** \brief The receive buffer overflowed and was cleared. */ + MODEM_EVENT_OVERFLOW, + + /** \brief The transmit buffer has been emptied. */ + MODEM_EVENT_TX_EMPTY } modemEvent_t; +/** \brief Type of a modem event handling function. */ typedef void (*MODEMEVENTHANDLERPROC)(modemEvent_t event); /* From modem.c */ +/** \brief Initialize the modem. + + This function initializes the modem for use. + + \retval 0 On failure. + \retval 1 On success. +*/ int modem_init(void); + +/** \brief Shut down the modem. + + This function shuts down the modem after it has been initialized, resetting + all of the registers to their defaults. +*/ void modem_shutdown(void); + +/** \brief Set the modem up for the specified mode. + + This function sets up the modem's registers for the specified mode and speed + combination. + + \param mode The mode to use. + \param speed The speed to use. + \see modem_modes + \see modem_v22bis + \see modem_v22 + \see modem_v32 + \see modem_v32bis + \see modem_v8 +*/ int modem_set_mode(int mode, modem_speed_t speed); + +/** \brief Wait for the modem to detect a dialtone. + + This function waits for a dialtone to be detected on the modem. + + \param ms_timeout The number of milliseconds to wait, in multiples of 100. + \retval 0 If a dialtone is detected before timeout. + \retval -1 If no dialtone is detected. +*/ int modem_wait_dialtone(int ms_timeout); + +/** \brief Dial the specified number on the modem. + \param digits The number to dial, as a string. + \retval 0 On failure. + \retval 1 On success. +*/ int modem_dial(const char *digits); + +/** \brief Set the event handler for the modem. + + This function sets up an event handler for when things happen on the modem. + + \param eventHandler The function to call when an event occurs. +*/ void modem_set_event_handler(MODEMEVENTHANDLERPROC eventHandler); + +/** \brief Disconnect the modem. + + This function instructs the modem to disconnect from the remote modem. +*/ void modem_disconnect(void); + +/** \brief Check if the modem is connecting. + \return 0 if the modem is not currently connecting, non-zero + otherwise. +*/ int modem_is_connecting(void); + +/** \brief Check if the modem is connected. + \return 0 if the modem is not currently connected, non-zero + otherwise. +*/ int modem_is_connected(void); + +/** \brief Get the connection rate that the modem is connected at. + \return The connection rate in bits per second. +*/ unsigned long modem_get_connection_rate(void); /* From mdata.c */ +/** \brief Read data from the modem buffers. + \param data The buffer to read into. + \param size The maximum number of bytes to read. + \return The actual number of bytes read. +*/ int modem_read_data(unsigned char *data, int size); + +/** \brief Write data to the modem buffers. + \param data The buffer to write from. + \param size The maximum number of bytes to write. + \return The actual number of bytes written. +*/ int modem_write_data(unsigned char *data, int size); + +/** \brief Check if the modem has data waiting to be read. + \return 0 if no data available, non-zero otherwise. +*/ int modem_has_data(void); #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-25 17:55:22
|
Revision: 690 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=690&view=rev Author: ljsebald Date: 2010-10-25 17:55:16 +0000 (Mon, 25 Oct 2010) Log Message: ----------- - Send an ICMPv6 parameter problem if we don't know how to handle a next_header value that we get in IPv6. - Call the IPv4 pseudo-header checksummer if we call the IPv6 one with IPv4 mapped addresses. Modified Paths: -------------- kos/kernel/net/net_ipv6.c Modified: kos/kernel/net/net_ipv6.c =================================================================== --- kos/kernel/net/net_ipv6.c 2010-10-23 02:19:27 UTC (rev 689) +++ kos/kernel/net/net_ipv6.c 2010-10-25 17:55:16 UTC (rev 690) @@ -198,8 +198,10 @@ return net_icmp6_input(src, ip, pkt + sizeof(ipv6_hdr_t), len); default: - /* XXXX: Send a parameter problem */ - return -1; + /* We don't know what to do with this packet, so send an ICMPv6 + message indicating that. */ + return net_icmp6_send_param_prob(src, ICMP6_PARAM_PROB_UNK_HEADER, + 6, pkt, pktsize); } return 0; @@ -218,6 +220,15 @@ them in from header processing, do this the hard way. */ memcpy(&ps.src_addr, src, sizeof(struct in6_addr)); memcpy(&ps.dst_addr, dst, sizeof(struct in6_addr)); + + /* If this is actually an IPv4 packet, do the calculation there instead. */ + if(IN6_IS_ADDR_V4MAPPED(&ps.src_addr) && + IN6_IS_ADDR_V4MAPPED(&ps.dst_addr)) { + return net_ipv4_checksum_pseudo(ps.src_addr.__s6_addr.__s6_addr32[3], + ps.dst_addr.__s6_addr.__s6_addr32[3], + next_hdr, (uint16)upper_len); + } + ps.upper_layer_len = htonl(upper_len); ps.next_header = next_hdr; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-23 02:19:33
|
Revision: 689 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=689&view=rev Author: ljsebald Date: 2010-10-23 02:19:27 +0000 (Sat, 23 Oct 2010) Log Message: ----------- Add struct sockaddr_storage. Modified Paths: -------------- kos/include/sys/socket.h Modified: kos/include/sys/socket.h =================================================================== --- kos/include/sys/socket.h 2010-10-21 00:36:29 UTC (rev 688) +++ kos/include/sys/socket.h 2010-10-23 02:19:27 UTC (rev 689) @@ -42,13 +42,49 @@ char sa_data[]; }; +/** \brief Size of the struct sockaddr_storage. + The size here is chosen for compatibility with anything that may expect the + struct sockaddr_storage to be of size 128. Technically, since there are no + current plans to support AF_UNIX sockets, this could be smaller, but most + implementations make it 128 bytes. +*/ +#define _SS_MAXSIZE 128 + +/** \brief Desired alignment of struct sockaddr_storage. */ +#define _SS_ALIGNSIZE (sizeof(__uint64_t)) + +/** \brief First padding size used within struct sockaddr_storage. */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(sa_family_t)) + +/** \brief Second padding size used within struct sockaddr_storage. */ +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(sa_family_t) + \ + _SS_PAD1SIZE + _SS_ALIGNSIZE)) + +/** \brief Socket address structure of appropriate size to hold any supported + socket type's addresses. + \headerfile sys/socket.h +*/ +struct sockaddr_storage { + /** \brief Address family. */ + sa_family_t ss_family; + + /** \brief First padding field. */ + char _ss_pad1[_SS_PAD1SIZE]; + + /** \brief Used to force alignment. */ + __uint64_t _ss_align; + + /** \brief Second padding field to fill up the space required. */ + char _ss_pad2[_SS_PAD2SIZE]; +}; + /** \brief Datagram socket type. This socket type specifies that the socket in question transmits datagrams that may or may not be reliably transmitted. With IPv4, this implies using UDP as the underlying protocol. */ -#define SOCK_DGRAM 1 +#define SOCK_DGRAM 1 /** \brief Internet domain sockets for use with IPv4 addresses. */ #define AF_INET 1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-21 00:36:36
|
Revision: 688 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=688&view=rev Author: ljsebald Date: 2010-10-21 00:36:29 +0000 (Thu, 21 Oct 2010) Log Message: ----------- - Add a net_ipv4_checksum_pseudo() function that calculates the checksum over just the pseudo header (like the net_ipv6_checksum_pseudo() function). - Make UDP use that new function, and clean up checksum handling a little bit in it in general. Modified Paths: -------------- kos/kernel/net/net_ipv4.c kos/kernel/net/net_ipv4.h kos/kernel/net/net_udp.c Modified: kos/kernel/net/net_ipv4.c =================================================================== --- kos/kernel/net/net_ipv4.c 2010-10-20 21:01:15 UTC (rev 687) +++ kos/kernel/net/net_ipv4.c 2010-10-21 00:36:29 UTC (rev 688) @@ -263,6 +263,13 @@ out[3] = (uint8) (addr & 0xFF); } +uint16 net_ipv4_checksum_pseudo(in_addr_t src, in_addr_t dst, uint8 proto, + uint16 len) { + ipv4_pseudo_hdr_t ps = { src, dst, 0, proto, htons(len) }; + + return ~net_ipv4_checksum((uint8 *)&ps, sizeof(ipv4_pseudo_hdr_t), 0); +} + net_ipv4_stats_t net_ipv4_get_stats() { return ipv4_stats; } Modified: kos/kernel/net/net_ipv4.h =================================================================== --- kos/kernel/net/net_ipv4.h 2010-10-20 21:01:15 UTC (rev 687) +++ kos/kernel/net/net_ipv4.h 2010-10-21 00:36:29 UTC (rev 688) @@ -24,12 +24,7 @@ uint8 zero; uint8 proto; uint16 length; - uint16 src_port; - uint16 dst_port; - uint16 hdrlength; - uint16 checksum; - uint8 data[1]; -} packed ip_pseudo_hdr_t; +} packed ipv4_pseudo_hdr_t; #undef packed uint16 net_ipv4_checksum(const uint8 *data, int bytes, uint16 start); @@ -40,6 +35,9 @@ int net_ipv4_input(netif_t *src, const uint8 *pkt, int pktsize); int net_ipv4_input_proto(netif_t *net, ip_hdr_t *ip, const uint8 *data); +uint16 net_ipv4_checksum_pseudo(in_addr_t src, in_addr_t dst, uint8 proto, + uint16 len); + /* In net_ipv4_frag.c */ int net_ipv4_frag_send(netif_t *net, ip_hdr_t *hdr, const uint8 *data, int size); Modified: kos/kernel/net/net_udp.c =================================================================== --- kos/kernel/net/net_udp.c 2010-10-20 21:01:15 UTC (rev 687) +++ kos/kernel/net/net_udp.c 2010-10-21 00:36:29 UTC (rev 688) @@ -500,9 +500,8 @@ } int net_udp_input(netif_t *src, ip_hdr_t *ip, const uint8 *data, int size) { - uint8 buf[size + 12]; - ip_pseudo_hdr_t *ps = (ip_pseudo_hdr_t *)buf; - uint16 checksum; + udp_hdr_t *hdr = (udp_hdr_t *)data; + uint16 cs; struct udp_sock *sock; struct udp_pkt *pkt; @@ -512,32 +511,17 @@ return -1; } - ps->src_addr = ip->src; - ps->dst_addr = ip->dest; - ps->zero = 0; - ps->proto = ip->protocol; - memcpy(&ps->src_port, data, size); - ps->length = htons(size); + cs = net_ipv4_checksum_pseudo(ip->src, ip->dest, ip->protocol, size); - if(ps->checksum != 0) { -#if 1 - checksum = ps->checksum; - ps->checksum = 0; - ps->checksum = net_ipv4_checksum(buf, size + 12, 0); - - if(checksum != ps->checksum) { - /* The checksums don't match, bail out */ - ++udp_stats.pkt_recv_bad_chksum; - return -1; + if(hdr->checksum != 0) { + /* If the checksum is right, we'll get zero back from the checksum + function */ + if(net_ipv4_checksum(data, size, cs)) { + /* The checksum was wrong, bail out */ + ++udp_stats.pkt_recv_bad_chksum; + return -1; + } } -#else - if(net_ipv4_checksum(buf, size + 12, 0)) { - /* The checksum was wrong, bail out */ - ++udp_stats.pkt_recv_bad_chksum; - return -1; - } -#endif - } if(mutex_trylock(udp_mutex)) { /* Considering this function is usually called in an IRQ, if the @@ -547,9 +531,9 @@ LIST_FOREACH(sock, &net_udp_sockets, sock_list) { /* See if we have a socket matching the description provided */ - if(sock->local_addr.sin_port == ps->dst_port && - ((sock->remote_addr.sin_port == ps->src_port && - sock->remote_addr.sin_addr.s_addr == ps->src_addr) || + if(sock->local_addr.sin_port == hdr->dst_port && + ((sock->remote_addr.sin_port == hdr->src_port && + sock->remote_addr.sin_addr.s_addr == ip->src) || (sock->remote_addr.sin_port == 0 && sock->remote_addr.sin_addr.s_addr == INADDR_ANY))) { pkt = (struct udp_pkt *) malloc(sizeof(struct udp_pkt)); @@ -559,9 +543,9 @@ pkt->from.sin_family = AF_INET; pkt->from.sin_addr.s_addr = ip->src; - pkt->from.sin_port = ps->src_port; + pkt->from.sin_port = hdr->src_port; - memcpy(pkt->data, ps->data, pkt->datasize); + memcpy(pkt->data, data + sizeof(udp_hdr_t), pkt->datasize); TAILQ_INSERT_TAIL(&sock->packets, pkt, pkt_queue); @@ -585,49 +569,43 @@ static int net_udp_send_raw(netif_t *net, uint32 src_ip, uint16 src_port, uint32 dst_ip, uint16 dst_port, const uint8 *data, int size, int flags) { - uint8 buf[size + 12 + sizeof(udp_hdr_t)]; - ip_pseudo_hdr_t *ps = (ip_pseudo_hdr_t *) buf; + uint8 buf[size + sizeof(udp_hdr_t)]; + udp_hdr_t *hdr = (udp_hdr_t *)buf; + uint16 cs; int err; - if(net == NULL && net_default_dev == NULL) { - errno = ENETDOWN; - ++udp_stats.pkt_send_failed; - return -1; + if(!net) { + net = net_default_dev; + + if(!net) { + errno = ENETDOWN; + ++udp_stats.pkt_send_failed; + return -1; + } } if(src_ip == INADDR_ANY) { - if(net == NULL && net_default_dev != NULL) { - ps->src_addr = htonl(net_ipv4_address(net_default_dev->ip_addr)); - } - else if(net != NULL) { - ps->src_addr = htonl(net_ipv4_address(net->ip_addr)); - } - else { + src_ip = htonl(net_ipv4_address(net->ip_addr)); + + if(src_ip == INADDR_ANY) { errno = ENETDOWN; ++udp_stats.pkt_send_failed; return -1; } } - else { - ps->src_addr = src_ip; - } - memcpy(ps->data, data, size); + memcpy(buf + sizeof(udp_hdr_t), data, size); size += sizeof(udp_hdr_t); + cs = net_ipv4_checksum_pseudo(src_ip, dst_ip, IPPROTO_UDP, size); - ps->dst_addr = dst_ip; - ps->zero = 0; - ps->proto = 17; - ps->length = htons(size); - ps->src_port = src_port; - ps->dst_port = dst_port; - ps->hdrlength = ps->length; - ps->checksum = 0; - ps->checksum = net_ipv4_checksum(buf, size + 12, 0); + hdr->src_port = src_port; + hdr->dst_port = dst_port; + hdr->length = size; + hdr->checksum = 0; + hdr->checksum = net_ipv4_checksum(buf, size, cs); /* Pass everything off to the network layer to do the rest. */ - err = net_ipv4_send(net, buf + 12, size, -1, 64, IPPROTO_UDP, ps->src_addr, - ps->dst_addr); + err = net_ipv4_send(net, buf, size, -1, 64, IPPROTO_UDP, src_ip, dst_ip); if(err < 0) { ++udp_stats.pkt_send_failed; return -1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-20 21:01:21
|
Revision: 687 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=687&view=rev Author: ljsebald Date: 2010-10-20 21:01:15 +0000 (Wed, 20 Oct 2010) Log Message: ----------- A few more networking things in this commit: - Reorganize ARP a bit so it can queue a packet like NDP does. - Add a few ICMPv6 error messages that can be sent. - Handle v4 mapped address in IPv6 by sending things onto the IPv4 layer to be sent. - Generate a random ID for IPv4 packets if none is given to aid in fragmentation/reassembly. Modified Paths: -------------- kos/include/kos/net.h kos/kernel/arch/dreamcast/fs/fs_dclsocket.c kos/kernel/net/net_arp.c kos/kernel/net/net_core.c kos/kernel/net/net_icmp6.c kos/kernel/net/net_icmp6.h kos/kernel/net/net_ipv4.c kos/kernel/net/net_ipv4.h kos/kernel/net/net_ipv6.c kos/kernel/net/net_ipv6.h kos/kernel/net/net_ndp.c kos/kernel/net/net_udp.c Modified: kos/include/kos/net.h =================================================================== --- kos/include/kos/net.h 2010-10-19 02:57:47 UTC (rev 686) +++ kos/include/kos/net.h 2010-10-20 21:01:15 UTC (rev 687) @@ -138,33 +138,43 @@ /* Define the list type */ LIST_HEAD(netif_list, knetif); +#ifdef PACKED +#undef PACKED +#endif -/* Structure describing an ARP entry; each entry contains a MAC address, - an IP address, and a timestamp from 'jiffies'. The timestamp allows - aging and eventual removal. */ -typedef struct netarp { - /* ARP cache list handle */ - LIST_ENTRY(netarp) ac_list; +#define PACKED __attribute__((packed)) - /* Mac address */ - uint8 mac[6]; +/* IPv4 Packet header */ +typedef struct { + uint8 version_ihl; + uint8 tos; + uint16 length; + uint16 packet_id; + uint16 flags_frag_offs; + uint8 ttl; + uint8 protocol; + uint16 checksum; + uint32 src; + uint32 dest; +} PACKED ip_hdr_t; - /* Associated IP address */ - uint8 ip[4]; +/* IPv6 Packet header */ +typedef struct ipv6_hdr_s { + uint8 version_lclass; + uint8 hclass_lflow; + uint16 lclass; + uint16 length; + uint8 next_header; + uint8 hop_limit; + struct in6_addr src_addr; + struct in6_addr dst_addr; +} PACKED ipv6_hdr_t; - /* Cache entry time; if zero, this entry won't expire */ - uint32 timestamp; -} netarp_t; +#undef PACKED -/* Define the list type */ -LIST_HEAD(netarp_list, netarp); /***** net_arp.c **********************************************************/ -/* ARP cache */ -extern struct netarp_list net_arp_cache; - - /* Init */ int net_arp_init(); @@ -178,10 +188,11 @@ int net_arp_insert(netif_t *nif, uint8 mac[6], uint8 ip[4], uint32 timestamp); /* Look up an entry from the ARP cache; if no entry is found, then an ARP - query will be sent and an error will be returned. Thus your packet send - should also fail. Later when the transmit retries, hopefully the answer - will have arrived. */ -int net_arp_lookup(netif_t *nif, uint8 ip_in[4], uint8 mac_out[6]); + query will be sent and an error will be returned. If you specify a packet + with the call, it will be sent when the reply comes in. pkt should be a + simple IPv4 header, data anything that comes after it. */ +int net_arp_lookup(netif_t *nif, uint8 ip_in[4], uint8 mac_out[6], + const ip_hdr_t *pkt, const uint8 *data, int data_size); /* Do a reverse ARP lookup: look for an IP for a given mac address; note that if this fails, you have no recourse. */ @@ -284,7 +295,7 @@ /* Send a Router Solicitation request on the specified interface */ int net_icmp6_send_rsol(netif_t *net); -/* Destination Unreachable codes */ +/* Destination Unreachable codes -- only port unreachable really makes sense */ #define ICMP6_DEST_UNREACH_NO_ROUTE 0 #define ICMP6_DEST_UNREACH_PROHIBITED 1 #define ICMP6_DEST_UNREACH_BEYOND_SCOPE 2 @@ -293,15 +304,25 @@ #define ICMP6_DEST_UNREACH_FAIL_EGRESS 5 #define ICMP6_DEST_UNREACH_BAD_ROUTE 6 -/* Time Exceeded codes */ +int net_icmp6_send_dest_unreach(netif_t *net, uint8 code, const uint8 *ppkt, + int psz); + +/* Time Exceeded codes -- only fragment reassembly time exceeded makes sense */ #define ICMP6_TIME_EXCEEDED_HOPS_EXC 0 #define ICMP6_TIME_EXCEEDED_FRAGMENT 1 +int net_icmp6_send_time_exceeded(netif_t *net, uint8 code, const uint8 *ppkt, + int psz); + /* Parameter Problem codes */ #define ICMP6_PARAM_PROB_BAD_HEADER 0 #define ICMP6_PARAM_PROB_UNK_HEADER 1 #define ICMP6_PARAM_PROB_UNK_OPTION 2 +/* Send an ICMPv6 Parameter Problem about the given packet. */ +int net_icmp6_send_param_prob(netif_t *net, uint8 code, uint32 ptr, + const uint8 *ppkt, int psz); + /***** net_ipv6.c *********************************************************/ /* IPv6 statistics structure. This structure holds some basic statistics about @@ -338,7 +359,7 @@ with the call, it will be sent when the reply comes in. pkt should be a simple IPv6 header, data anything that comes after it. */ int net_ndp_lookup(netif_t *net, const struct in6_addr *ip, uint8 mac_out[6], - const void *pkt, const uint8 *data, int data_size); + const ipv6_hdr_t *pkt, const uint8 *data, int data_size); /***** net_udp.c **********************************************************/ Modified: kos/kernel/arch/dreamcast/fs/fs_dclsocket.c =================================================================== --- kos/kernel/arch/dreamcast/fs/fs_dclsocket.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/arch/dreamcast/fs/fs_dclsocket.c 2010-10-20 21:01:15 UTC (rev 687) @@ -734,9 +734,9 @@ /* Put dc-tool's info into our ARP cache */ net_ipv4_parse_address(ip, ipaddr); - err = net_arp_lookup(net_default_dev, ipaddr, mac); + err = net_arp_lookup(net_default_dev, ipaddr, mac, NULL, NULL, 0); while(err == -1 || err == -2) { - err = net_arp_lookup(net_default_dev, ipaddr, mac); + err = net_arp_lookup(net_default_dev, ipaddr, mac, NULL, NULL, 0); } /* Make the entry permanent */ Modified: kos/kernel/net/net_arp.c =================================================================== --- kos/kernel/net/net_arp.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_arp.c 2010-10-20 21:01:15 UTC (rev 687) @@ -3,7 +3,7 @@ kernel/net/net_arp.c Copyright (C) 2002 Dan Potter - Copyright (C) 2005 Lawrence Sebald + Copyright (C) 2005, 2010 Lawrence Sebald */ #include <string.h> @@ -11,6 +11,7 @@ #include <stdio.h> #include <kos/net.h> #include <kos/thread.h> + #include "net_ipv4.h" /* @@ -22,225 +23,301 @@ /* ARP Packet Structre */ #define packed __attribute__((packed)) typedef struct { - uint8 hw_type[2]; - uint8 pr_type[2]; - uint8 hw_size; - uint8 pr_size; - uint8 opcode[2]; - uint8 hw_send[6]; - uint8 pr_send[4]; - uint8 hw_recv[6]; - uint8 pr_recv[6]; + uint8 hw_type[2]; + uint8 pr_type[2]; + uint8 hw_size; + uint8 pr_size; + uint8 opcode[2]; + uint8 hw_send[6]; + uint8 pr_send[4]; + uint8 hw_recv[6]; + uint8 pr_recv[6]; } packed arp_pkt_t; #undef packed +/* Structure describing an ARP entry; each entry contains a MAC address, + an IP address, and a timestamp from 'jiffies'. The timestamp allows + aging and eventual removal. */ +typedef struct netarp { + /* ARP cache list handle */ + LIST_ENTRY(netarp) ac_list; + + /* Mac address */ + uint8 mac[6]; + + /* Associated IP address */ + uint8 ip[4]; + + /* Cache entry time; if zero, this entry won't expire */ + uint32 timestamp; + + /* Optional packet to send when the entry is filled in */ + ip_hdr_t *pkt; + + /* Additional data for that packet, if any */ + uint8 *data; + + /* Size of the additional data for the packet */ + int data_size; +} netarp_t; + +/* Define the list type */ +LIST_HEAD(netarp_list, netarp); + /**************************************************************************/ /* Variables */ /* ARP cache */ -struct netarp_list net_arp_cache; +struct netarp_list net_arp_cache = LIST_HEAD_INITIALIZER(0); /**************************************************************************/ /* Cache management */ /* Garbage collect timed out entries */ int net_arp_gc() { - netarp_t *a1, *a2; + netarp_t *a1, *a2; - a1 = LIST_FIRST(&net_arp_cache); - while (a1 != NULL) { - a2 = LIST_NEXT(a1, ac_list); - if (a1->timestamp && jiffies >= (a1->timestamp + 600*HZ)) { - LIST_REMOVE(a1, ac_list); - free(a1); - } - a1 = a2; - } + a1 = LIST_FIRST(&net_arp_cache); + while (a1 != NULL) { + a2 = LIST_NEXT(a1, ac_list); - return 0; + if (a1->timestamp && jiffies >= (a1->timestamp + 600*HZ)) { + LIST_REMOVE(a1, ac_list); + + if(a1->pkt) { + free(a1->pkt); + free(a1->data); + } + + free(a1); + } + a1 = a2; + } + + return 0; } /* Add an entry to the ARP cache manually */ int net_arp_insert(netif_t *nif, uint8 mac[6], uint8 ip[4], uint32 timestamp) { - netarp_t *cur; - - /* First make sure the entry isn't already there */ - LIST_FOREACH(cur, &net_arp_cache, ac_list) { - if (!memcmp(ip, cur->ip, 4)) { - memcpy(cur->mac, mac, 6); - cur->timestamp = timestamp; - return 0; - } - } + netarp_t *cur; - /* It's not there, add an entry */ - cur = (netarp_t *)malloc(sizeof(netarp_t)); - memcpy(cur->mac, mac, 6); - memcpy(cur->ip, ip, 4); - cur->timestamp = timestamp; - LIST_INSERT_HEAD(&net_arp_cache, cur, ac_list); + /* First make sure the entry isn't already there */ + LIST_FOREACH(cur, &net_arp_cache, ac_list) { + if (!memcmp(ip, cur->ip, 4)) { + memcpy(cur->mac, mac, 6); + cur->timestamp = timestamp; - /* Garbage collect expired entries */ - net_arp_gc(); + /* Send our queued packet, if we have one */ + if(cur->pkt) { + net_ipv4_send_packet(nif, cur->pkt, cur->data, cur->data_size); + free(cur->pkt); + free(cur->data); - return 0; + cur->pkt = NULL; + cur->data = NULL; + cur->data_size = 0; + } + + return 0; + } + } + + /* It's not there, add an entry */ + cur = (netarp_t *)malloc(sizeof(netarp_t)); + memcpy(cur->mac, mac, 6); + memcpy(cur->ip, ip, 4); + cur->timestamp = timestamp; + cur->pkt = NULL; + cur->data = NULL; + cur->data_size = 0; + LIST_INSERT_HEAD(&net_arp_cache, cur, ac_list); + + /* Garbage collect expired entries */ + net_arp_gc(); + + return 0; } /* Look up an entry from the ARP cache; if no entry is found, then an ARP query will be sent and an error will be returned. Thus your packet send should also fail. Later when the transmit retries, hopefully the answer will have arrived. */ -int net_arp_lookup(netif_t *nif, uint8 ip_in[4], uint8 mac_out[6]) { - netarp_t *cur; +int net_arp_lookup(netif_t *nif, uint8 ip_in[4], uint8 mac_out[6], + const ip_hdr_t *pkt, const uint8 *data, int data_size) { + netarp_t *cur; - /* Garbage collect expired entries */ - net_arp_gc(); + /* Garbage collect expired entries */ + net_arp_gc(); - /* Look for the entry */ - LIST_FOREACH(cur, &net_arp_cache, ac_list) { - if (!memcmp(ip_in, cur->ip, 4)) { - if(cur->mac[0] == 0 && cur->mac[1] == 0 && - cur->mac[2] == 0 && cur->mac[3] == 0 && - cur->mac[4] == 0 && cur->mac[5] == 0) { - return -1; - } + /* Look for the entry */ + LIST_FOREACH(cur, &net_arp_cache, ac_list) { + if (!memcmp(ip_in, cur->ip, 4)) { + if(cur->mac[0] == 0 && cur->mac[1] == 0 && + cur->mac[2] == 0 && cur->mac[3] == 0 && + cur->mac[4] == 0 && cur->mac[5] == 0) { + return -1; + } - memcpy(mac_out, cur->mac, 6); - if (cur->timestamp != 0) - cur->timestamp = jiffies; - return 0; - } - } + memcpy(mac_out, cur->mac, 6); + if (cur->timestamp != 0) + cur->timestamp = jiffies; + return 0; + } + } - /* It's not there... Add an incomplete ARP entry */ - memset(mac_out, 0, 6); - net_arp_insert(nif, mac_out, ip_in, jiffies); - - /* Generate an ARP who-has packet */ - net_arp_query(nif, ip_in); + /* It's not there... Add an incomplete ARP entry */ + cur = (netarp_t *)malloc(sizeof(netarp_t)); + memset(cur, 0, sizeof(netarp_t)); + memcpy(cur->ip, ip_in, 4); + cur->timestamp = jiffies; - /* Return failure */ - return -2; + /* Copy our packet if we have one to copy. */ + if(pkt && data && data_size) { + cur->data = (uint8 *)malloc(data_size); + + if(cur->data) { + cur->pkt = (ip_hdr_t *)malloc(sizeof(ip_hdr_t)); + + if(!cur->pkt) { + free(cur->data); + cur->data = NULL; + } + else { + memcpy(cur->pkt, pkt, sizeof(ip_hdr_t)); + memcpy(cur->data, data, data_size); + cur->data_size = data_size; + } + } + } + + LIST_INSERT_HEAD(&net_arp_cache, cur, ac_list); + + /* Generate an ARP who-has packet */ + net_arp_query(nif, ip_in); + + /* Return failure */ + memset(mac_out, 0, 6); + return -2; } /* Do a reverse ARP lookup: look for an IP for a given mac address; note that if this fails, you have no recourse. */ int net_arp_revlookup(netif_t *nif, uint8 ip_out[4], uint8 mac_in[6]) { - netarp_t *cur; + netarp_t *cur; - /* Look for the entry */ - LIST_FOREACH(cur, &net_arp_cache, ac_list) { - if (!memcmp(mac_in, cur->mac, 6)) { - memcpy(ip_out, cur->ip, 4); - if (cur->timestamp != 0) - cur->timestamp = jiffies; - return 0; - } - } + /* Look for the entry */ + LIST_FOREACH(cur, &net_arp_cache, ac_list) { + if (!memcmp(mac_in, cur->mac, 6)) { + memcpy(ip_out, cur->ip, 4); + if (cur->timestamp != 0) + cur->timestamp = jiffies; + return 0; + } + } - return -1; + return -1; } /* Send an ARP reply packet on the specified network adapter */ static int net_arp_send(netif_t *nif, arp_pkt_t *pkt) { - arp_pkt_t pkt_out; - eth_hdr_t eth_hdr; - uint8 buf[sizeof(arp_pkt_t) + sizeof(eth_hdr_t)]; + arp_pkt_t pkt_out; + eth_hdr_t eth_hdr; + uint8 buf[sizeof(arp_pkt_t) + sizeof(eth_hdr_t)]; - /* First, fill in the ARP packet. */ - pkt_out.hw_type[0] = 0; - pkt_out.hw_type[1] = 1; - pkt_out.pr_type[0] = 0x08; - pkt_out.pr_type[1] = 0x00; - pkt_out.hw_size = 6; - pkt_out.pr_size = 4; - pkt_out.opcode[0] = 0; - pkt_out.opcode[1] = 2; - memcpy(pkt_out.hw_send, nif->mac_addr, 6); - memcpy(pkt_out.pr_send, nif->ip_addr, 4); - memcpy(pkt_out.pr_recv, pkt->pr_send, 4); - memcpy(pkt_out.hw_recv, pkt->hw_send, 6); + /* First, fill in the ARP packet. */ + pkt_out.hw_type[0] = 0; + pkt_out.hw_type[1] = 1; + pkt_out.pr_type[0] = 0x08; + pkt_out.pr_type[1] = 0x00; + pkt_out.hw_size = 6; + pkt_out.pr_size = 4; + pkt_out.opcode[0] = 0; + pkt_out.opcode[1] = 2; + memcpy(pkt_out.hw_send, nif->mac_addr, 6); + memcpy(pkt_out.pr_send, nif->ip_addr, 4); + memcpy(pkt_out.pr_recv, pkt->pr_send, 4); + memcpy(pkt_out.hw_recv, pkt->hw_send, 6); - /* Fill in the ethernet header. */ - memcpy(eth_hdr.src, nif->mac_addr, 6); - memcpy(eth_hdr.dest, pkt->hw_send, 6); - eth_hdr.type[0] = 0x08; /* ARP */ - eth_hdr.type[1] = 0x06; + /* Fill in the ethernet header. */ + memcpy(eth_hdr.src, nif->mac_addr, 6); + memcpy(eth_hdr.dest, pkt->hw_send, 6); + eth_hdr.type[0] = 0x08; /* ARP */ + eth_hdr.type[1] = 0x06; - memcpy(buf, ð_hdr, sizeof(eth_hdr_t)); - memcpy(buf + sizeof(eth_hdr_t), &pkt_out, sizeof(arp_pkt_t)); + memcpy(buf, ð_hdr, sizeof(eth_hdr_t)); + memcpy(buf + sizeof(eth_hdr_t), &pkt_out, sizeof(arp_pkt_t)); - /* Send it away */ - nif->if_tx(nif, buf, sizeof(eth_hdr_t) + sizeof(arp_pkt_t), NETIF_BLOCK); - - return 0; + /* Send it away */ + nif->if_tx(nif, buf, sizeof(eth_hdr_t) + sizeof(arp_pkt_t), NETIF_BLOCK); + + return 0; } /* Receive an ARP packet and process it (called by net_input) */ int net_arp_input(netif_t *nif, const uint8 *pkt_in, int len) { - eth_hdr_t *eth_hdr; - arp_pkt_t *pkt; + eth_hdr_t *eth_hdr; + arp_pkt_t *pkt; - eth_hdr = (eth_hdr_t *)pkt_in; - pkt = (arp_pkt_t *)(pkt_in + sizeof(eth_hdr_t)); + eth_hdr = (eth_hdr_t *)pkt_in; + pkt = (arp_pkt_t *)(pkt_in + sizeof(eth_hdr_t)); - switch(pkt->opcode[1]) { - case 1: /* ARP Request */ - net_arp_send(nif, pkt); - case 2: /* ARP Reply */ - /* Insert into ARP cache */ - net_arp_insert(nif, pkt->hw_send, pkt->pr_send, jiffies); - break; - default: - dbglog(DBG_KDEBUG, "net_arp: Unknown ARP Opcode: %d\n", pkt->opcode[1]); - } + switch(pkt->opcode[1]) { + case 1: /* ARP Request */ + net_arp_send(nif, pkt); + case 2: /* ARP Reply */ + /* Insert into ARP cache */ + net_arp_insert(nif, pkt->hw_send, pkt->pr_send, jiffies); + break; + default: + dbglog(DBG_KDEBUG, "net_arp: Unknown ARP Opcode: %d\n", pkt->opcode[1]); + } - return 0; + return 0; } /* Generate an ARP who-has query on the given device */ int net_arp_query(netif_t *nif, uint8 ip[4]) { - arp_pkt_t pkt_out; - eth_hdr_t eth_hdr; - uint8 buf[sizeof(arp_pkt_t) + sizeof(eth_hdr_t)]; + arp_pkt_t pkt_out; + eth_hdr_t eth_hdr; + uint8 buf[sizeof(arp_pkt_t) + sizeof(eth_hdr_t)]; - /* First, fill in the ARP packet. */ - pkt_out.hw_type[0] = 0; - pkt_out.hw_type[1] = 1; - pkt_out.pr_type[0] = 0x08; - pkt_out.pr_type[1] = 0x00; - pkt_out.hw_size = 6; - pkt_out.pr_size = 4; - pkt_out.opcode[0] = 0; - pkt_out.opcode[1] = 1; - memcpy(pkt_out.hw_send, nif->mac_addr, 6); - memcpy(pkt_out.pr_send, nif->ip_addr, 4); - memcpy(pkt_out.pr_recv, ip, 4); - pkt_out.hw_recv[0] = 0xFF; /* Ethernet broadcast address */ - pkt_out.hw_recv[1] = 0xFF; - pkt_out.hw_recv[2] = 0xFF; - pkt_out.hw_recv[3] = 0xFF; - pkt_out.hw_recv[4] = 0xFF; - pkt_out.hw_recv[5] = 0xFF; + /* First, fill in the ARP packet. */ + pkt_out.hw_type[0] = 0; + pkt_out.hw_type[1] = 1; + pkt_out.pr_type[0] = 0x08; + pkt_out.pr_type[1] = 0x00; + pkt_out.hw_size = 6; + pkt_out.pr_size = 4; + pkt_out.opcode[0] = 0; + pkt_out.opcode[1] = 1; + memcpy(pkt_out.hw_send, nif->mac_addr, 6); + memcpy(pkt_out.pr_send, nif->ip_addr, 4); + memcpy(pkt_out.pr_recv, ip, 4); + pkt_out.hw_recv[0] = 0xFF; /* Ethernet broadcast address */ + pkt_out.hw_recv[1] = 0xFF; + pkt_out.hw_recv[2] = 0xFF; + pkt_out.hw_recv[3] = 0xFF; + pkt_out.hw_recv[4] = 0xFF; + pkt_out.hw_recv[5] = 0xFF; - /* Fill in the ethernet header. */ - memcpy(eth_hdr.src, nif->mac_addr, 6); - eth_hdr.dest[0] = 0xFF; /* Ethernet broadcast address */ - eth_hdr.dest[1] = 0xFF; - eth_hdr.dest[2] = 0xFF; - eth_hdr.dest[3] = 0xFF; - eth_hdr.dest[4] = 0xFF; - eth_hdr.dest[5] = 0xFF; - eth_hdr.type[0] = 0x08; /* ARP */ - eth_hdr.type[1] = 0x06; + /* Fill in the ethernet header. */ + memcpy(eth_hdr.src, nif->mac_addr, 6); + eth_hdr.dest[0] = 0xFF; /* Ethernet broadcast address */ + eth_hdr.dest[1] = 0xFF; + eth_hdr.dest[2] = 0xFF; + eth_hdr.dest[3] = 0xFF; + eth_hdr.dest[4] = 0xFF; + eth_hdr.dest[5] = 0xFF; + eth_hdr.type[0] = 0x08; /* ARP */ + eth_hdr.type[1] = 0x06; - memcpy(buf, ð_hdr, sizeof(eth_hdr_t)); - memcpy(buf + sizeof(eth_hdr_t), &pkt_out, sizeof(arp_pkt_t)); + memcpy(buf, ð_hdr, sizeof(eth_hdr_t)); + memcpy(buf + sizeof(eth_hdr_t), &pkt_out, sizeof(arp_pkt_t)); - /* Send it away */ - nif->if_tx(nif, buf, sizeof(eth_hdr_t) + sizeof(arp_pkt_t), NETIF_BLOCK); - - return 0; + /* Send it away */ + nif->if_tx(nif, buf, sizeof(eth_hdr_t) + sizeof(arp_pkt_t), NETIF_BLOCK); + + return 0; } /*****************************************************************************/ @@ -248,23 +325,23 @@ /* Init */ int net_arp_init() { - /* Initialize the ARP cache */ - LIST_INIT(&net_arp_cache); + /* Initialize the ARP cache */ + LIST_INIT(&net_arp_cache); - return 0; + return 0; } /* Shutdown */ void net_arp_shutdown() { - /* Free all ARP entries */ - netarp_t *a1, *a2; + /* Free all ARP entries */ + netarp_t *a1, *a2; - a1 = LIST_FIRST(&net_arp_cache); - while (a1 != NULL) { - a2 = LIST_NEXT(a1, ac_list); - free(a1); - a1 = a2; - } + a1 = LIST_FIRST(&net_arp_cache); + while (a1 != NULL) { + a2 = LIST_NEXT(a1, ac_list); + free(a1); + a1 = a2; + } - LIST_INIT(&net_arp_cache); + LIST_INIT(&net_arp_cache); } Modified: kos/kernel/net/net_core.c =================================================================== --- kos/kernel/net/net_core.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_core.c 2010-10-20 21:01:15 UTC (rev 687) @@ -35,9 +35,6 @@ /* Active network devices list */ struct netif_list net_if_list = LIST_HEAD_INITIALIZER(0); -/* ARP cache */ -struct netarp_list net_arp_cache = LIST_HEAD_INITIALIZER(0); - /* Are we already initialized? */ static int net_initted = 0; Modified: kos/kernel/net/net_icmp6.c =================================================================== --- kos/kernel/net/net_icmp6.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_icmp6.c 2010-10-20 21:01:15 UTC (rev 687) @@ -20,6 +20,9 @@ This file implements RFC 4443, the Internet Control Message Protocol for IPv6. All messages mentioned below are from that RFC, unless otherwise specified. Currently implemented message types are: + 1 - Destination Unreachable -- Sending only + 3 - Time Exceeded -- Sending only + 4 - Parameter Problem -- Sending only 128 - Echo 129 - Echo Reply 133 - Router Solicitation (RFC 4861) -- Sending only @@ -29,10 +32,7 @@ 137 - Redirect (RFC 4861) -- partial Message types that are not implemented yet (if ever): - 1 - Destination Unreachable 2 - Packet Too Big - 3 - Time Exceeded - 4 - Parameter Problem Any other numbers not listed in the first list... */ @@ -670,3 +670,126 @@ return net_ipv6_send(net, databuf, size, 255, IPV6_HDR_ICMP, &src, &in6addr_linklocal_allrouters); } + +/* Convenience function for handling the parts of error packets that are the + same no matter what kind we're dealing with. */ +static int send_err_pkt(netif_t *net, uint8 buf[1240], int ptr, + const uint8 *ppkt, int pktsz, int mc_allow) { + int size = 1240 - ptr; + icmp6_hdr_t *pkt = (icmp6_hdr_t *)buf; + const ipv6_hdr_t *orig = (const ipv6_hdr_t *)ppkt; + uint16 cs; + struct in6_addr osrc, odst, src; + + /* Copy out the original source and destination addresses */ + memcpy(&osrc, &orig->src_addr, sizeof(struct in6_addr)); + memcpy(&odst, &orig->dst_addr, sizeof(struct in6_addr)); + + /* Figure out if we should actually send a message or not */ + if(IN6_IS_ADDR_UNSPECIFIED(&osrc) || IN6_IS_ADDR_MULTICAST(&osrc)) { + /* Don't send for any packets that have an unspecified or multicast + source address. */ + return 0; + } + + if(!mc_allow && IN6_IS_ADDR_MULTICAST(&odst)) { + /* Don't send anything where the destination is a multicast unless it + is specifically allowed (examples: packet too big and the parameter + problem code 2). */ + return 0; + } + + /* Pick the address we'll send from */ + if(IN6_IS_ADDR_LINKLOCAL(&odst) || IN6_IS_ADDR_MC_LINKLOCAL(&odst)) { + src = net->ip6_lladdr; + } + else if(net->ip6_addr_count) { + src = net->ip6_addrs[0]; + } + else { + return -1; + } + + if(size > pktsz) { + memcpy(&buf[ptr], ppkt, pktsz); + size = ptr + pktsz; + } + else { + memcpy(&buf[ptr], ppkt, size); + size = 1240; + } + + /* Compute the ICMP Checksum */ + cs = net_ipv6_checksum_pseudo(&src, &osrc, size, IPV6_HDR_ICMP); + pkt->checksum = net_ipv4_checksum(buf, size, cs); + + /* Send it away */ + return net_ipv6_send(net, buf, size, 0, IPV6_HDR_ICMP, &src, &osrc); +} + +/* Send an ICMPv6 Destination Unreachable about the given packet. */ +int net_icmp6_send_dest_unreach(netif_t *net, uint8 code, const uint8 *ppkt, + int psz) { + uint8 buf[1240]; + icmp6_dest_unreach_t *pkt = (icmp6_dest_unreach_t *)buf; + + /* Make sure the given code is sane */ + if(code > ICMP6_DEST_UNREACH_BAD_ROUTE) { + return -1; + } + + /* Fill in the unique part of the message, and leave the rest to the general + error handling. */ + pkt->type = ICMP6_MESSAGE_DEST_UNREACHABLE; + pkt->code = code; + pkt->unused = 0; + + return send_err_pkt(net, buf, sizeof(icmp6_dest_unreach_t), ppkt, psz, 0); +} + +/* Send an ICMPv6 Time Exceeded about the given packet. */ +int net_icmp6_send_time_exceeded(netif_t *net, uint8 code, const uint8 *ppkt, + int psz) { + uint8 buf[1240]; + icmp6_time_exceeded_t *pkt = (icmp6_time_exceeded_t *)buf; + + /* Make sure the given code is sane */ + if(code > ICMP6_TIME_EXCEEDED_FRAGMENT) { + return -1; + } + + /* Fill in the unique part of the message, and leave the rest to the general + error handling. */ + pkt->type = ICMP6_MESSAGE_TIME_EXCEEDED; + pkt->code = code; + pkt->unused = 0; + + return send_err_pkt(net, buf, sizeof(icmp6_time_exceeded_t), ppkt, psz, 0); +} + +/* Send an ICMPv6 Parameter Problem about the given packet. */ +int net_icmp6_send_param_prob(netif_t *net, uint8 code, uint32 ptr, + const uint8 *ppkt, int psz) { + uint8 buf[1240]; + icmp6_param_problem_t *pkt = (icmp6_param_problem_t *)buf; + int mc_allow = 0; + + /* Make sure the given code is sane */ + if(code > ICMP6_PARAM_PROB_UNK_OPTION) { + return -1; + } + + /* Do we allow sending this as a result of a multicast? */ + if(code == ICMP6_PARAM_PROB_UNK_OPTION) { + mc_allow = 1; + } + + /* Fill in the unique part of the message, and leave the rest to the general + error handling. */ + pkt->type = ICMP6_MESSAGE_PARAM_PROBLEM; + pkt->code = code; + pkt->ptr = ntohl(ptr); + + return send_err_pkt(net, buf, sizeof(icmp6_param_problem_t), ppkt, psz, + mc_allow); +} Modified: kos/kernel/net/net_icmp6.h =================================================================== --- kos/kernel/net/net_icmp6.h 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_icmp6.h 2010-10-20 21:01:15 UTC (rev 687) @@ -28,7 +28,7 @@ uint8 type; uint8 code; uint16 checksum; - uint32 reserved; + uint32 unused; } PACKED icmp6_dest_unreach_t; /* Header for Packet Too Big packets (type 2) */ Modified: kos/kernel/net/net_ipv4.c =================================================================== --- kos/kernel/net/net_ipv4.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_ipv4.c 2010-10-20 21:01:15 UTC (rev 687) @@ -10,6 +10,7 @@ */ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <errno.h> #include <arpa/inet.h> @@ -130,15 +131,16 @@ /* Get our destination's MAC address. If we do not have the MAC address cached, return a distinguished error to the upper-level protocol so that it can decide what to do. */ - err = net_arp_lookup(net, dest_ip, dest_mac); + err = net_arp_lookup(net, dest_ip, dest_mac, hdr, data, size); if(err == -1) { errno = ENETUNREACH; ++ipv4_stats.pkt_send_failed; return -1; } else if(err == -2) { - ++ipv4_stats.pkt_send_failed; - return -2; + /* It'll send when the ARP reply comes in (assuming one does), so + return success. */ + return 0; } } @@ -167,6 +169,12 @@ int proto, uint32 src, uint32 dst) { ip_hdr_t hdr; + /* If the ID is -1, generate a random ID value that can be used in case the + packet gets fragmented. */ + if(id == -1) { + id = rand() & 0xFFFF; + } + /* Fill in the IPv4 Header */ hdr.version_ihl = 0x45; hdr.tos = 0; Modified: kos/kernel/net/net_ipv4.h =================================================================== --- kos/kernel/net/net_ipv4.h 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_ipv4.h 2010-10-20 21:01:15 UTC (rev 687) @@ -8,6 +8,8 @@ #ifndef __LOCAL_NET_IPV4_H #define __LOCAL_NET_IPV4_H +#include <kos/net.h> + /* These structs are from AndrewK's dcload-ip. */ #define packed __attribute__((packed)) typedef struct { @@ -17,19 +19,6 @@ } packed eth_hdr_t; typedef struct { - uint8 version_ihl; - uint8 tos; - uint16 length; - uint16 packet_id; - uint16 flags_frag_offs; - uint8 ttl; - uint8 protocol; - uint16 checksum; - uint32 src; - uint32 dest; -} packed ip_hdr_t; - -typedef struct { uint32 src_addr; uint32 dst_addr; uint8 zero; Modified: kos/kernel/net/net_ipv6.c =================================================================== --- kos/kernel/net/net_ipv6.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_ipv6.c 2010-10-20 21:01:15 UTC (rev 687) @@ -131,6 +131,19 @@ } } + /* If this is actually going both to and from an IPv4 address, use the IPv4 + send function to do the rest. Note that only V4-mapped addresses are + supported here (::ffff:x.y.z.w) */ + if(IN6_IS_ADDR_V4MAPPED(src) && IN6_IS_ADDR_V4MAPPED(dst)) { + return net_ipv4_send(net, data, data_size, -1, hop_limit, proto, + src->__s6_addr.__s6_addr32[3], + dst->__s6_addr.__s6_addr32[3]); + } + else if(IN6_IS_ADDR_V4MAPPED(src) || IN6_IS_ADDR_V4MAPPED(dst) || + IN6_IS_ADDR_V4COMPAT(src) || IN6_IS_ADDR_V4COMPAT(dst)) { + return -1; + } + hdr.version_lclass = 0x60; hdr.hclass_lflow = 0; hdr.lclass = 0; Modified: kos/kernel/net/net_ipv6.h =================================================================== --- kos/kernel/net/net_ipv6.h 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_ipv6.h 2010-10-20 21:01:15 UTC (rev 687) @@ -8,7 +8,7 @@ #ifndef __LOCAL_NET_IPV6_H #define __LOCAL_NET_IPV6_H -#include <netinet/in.h> +#include <kos/net.h> #ifdef PACKED #undef PACKED @@ -16,17 +16,6 @@ #define PACKED __attribute__((packed)) -typedef struct ipv6_hdr_s { - uint8 version_lclass; - uint8 hclass_lflow; - uint16 lclass; - uint16 length; - uint8 next_header; - uint8 hop_limit; - struct in6_addr src_addr; - struct in6_addr dst_addr; -} PACKED ipv6_hdr_t; - typedef struct ipv6_ext_hdr_s { uint8 next_header; uint8 ext_length; Modified: kos/kernel/net/net_ndp.c =================================================================== --- kos/kernel/net/net_ndp.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_ndp.c 2010-10-20 21:01:15 UTC (rev 687) @@ -156,7 +156,7 @@ } int net_ndp_lookup(netif_t *net, const struct in6_addr *ip, uint8 mac_out[6], - const void *pkt, const uint8 *data, int data_size) { + const ipv6_hdr_t *pkt, const uint8 *data, int data_size) { ndp_entry_t *i; uint64 now = timer_ms_gettime64(); @@ -227,6 +227,12 @@ i = LIST_FIRST(&ndp_cache); while(i) { tmp = LIST_NEXT(i, entry); + + if(i->pkt) { + free(i->pkt); + free(i->data); + } + free(i); i = tmp; } Modified: kos/kernel/net/net_udp.c =================================================================== --- kos/kernel/net/net_udp.c 2010-10-19 02:57:47 UTC (rev 686) +++ kos/kernel/net/net_udp.c 2010-10-20 21:01:15 UTC (rev 687) @@ -17,7 +17,9 @@ #include <kos/fs_socket.h> #include <arch/irq.h> #include <sys/socket.h> + #include "net_ipv4.h" +#include "net_ipv6.h" #include "net_udp.h" #define packed __attribute__((packed)) @@ -517,6 +519,7 @@ memcpy(&ps->src_port, data, size); ps->length = htons(size); + if(ps->checksum != 0) { #if 1 checksum = ps->checksum; ps->checksum = 0; @@ -534,6 +537,7 @@ return -1; } #endif + } if(mutex_trylock(udp_mutex)) { /* Considering this function is usually called in an IRQ, if the @@ -621,27 +625,13 @@ ps->checksum = 0; ps->checksum = net_ipv4_checksum(buf, size + 12, 0); -retry_send: /* Pass everything off to the network layer to do the rest. */ - err = net_ipv4_send(net, buf + 12, size, 0, 64, IPPROTO_UDP, ps->src_addr, + err = net_ipv4_send(net, buf + 12, size, -1, 64, IPPROTO_UDP, ps->src_addr, ps->dst_addr); - - /* If the IP layer returns that the ARP cache didn't have the entry for the - destination, sleep for a little bit, and try again (as long as the - non-blocking flag was not set). */ - if(err == -2 && !(flags & O_NONBLOCK)) { - thd_sleep(100); - goto retry_send; - } - else if(err == -2) { - errno = ENETUNREACH; + if(err < 0) { ++udp_stats.pkt_send_failed; return -1; } - else if(err < 0) { - ++udp_stats.pkt_send_failed; - return -1; - } else { ++udp_stats.pkt_sent; return size - sizeof(udp_hdr_t); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-19 02:57:53
|
Revision: 686 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=686&view=rev Author: ljsebald Date: 2010-10-19 02:57:47 +0000 (Tue, 19 Oct 2010) Log Message: ----------- Reverting r671 for stream.drv. It shouldn't have ever been changed in the first place. Modified Paths: -------------- kos/kernel/arch/dreamcast/sound/arm/stream.drv Modified: kos/kernel/arch/dreamcast/sound/arm/stream.drv =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-18 18:33:24
|
Revision: 685 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=685&view=rev Author: ljsebald Date: 2010-10-18 18:33:14 +0000 (Mon, 18 Oct 2010) Log Message: ----------- Adding in a whole bunch of stuff that's been worked on over the past few days: - Adding CRC32 functions (both little and big endian versions). - Adding in support in the lan adapter and bba drivers for multicast packets (lan version still needs testing). - Adding in a wrapper around the multicast support in the la and bba drivers to handle things at a bit higher of a level. - Adding in real support for IPv6 (currently limited to ICMPv6 messages). - Adding in support for NDP (IPv6's equivalent of ARP -- done with ICMPv6 packets). - Adding in a IPv6 ping example. The IPv6 stuff should all be considered experimental at this point! Modified Paths: -------------- kos/examples/dreamcast/network/Makefile kos/include/kos/net.h kos/kernel/arch/dreamcast/hardware/network/broadband_adapter.c kos/kernel/arch/dreamcast/hardware/network/lan_adapter.c kos/kernel/net/Makefile kos/kernel/net/net_core.c kos/kernel/net/net_icmp.c kos/kernel/net/net_input.c kos/kernel/net/net_ipv6.c Added Paths: ----------- kos/examples/dreamcast/network/ping6/ kos/examples/dreamcast/network/ping6/Makefile kos/examples/dreamcast/network/ping6/ping.c kos/kernel/net/net_crc.c kos/kernel/net/net_icmp6.c kos/kernel/net/net_icmp6.h kos/kernel/net/net_ipv6.h kos/kernel/net/net_multicast.c kos/kernel/net/net_ndp.c Modified: kos/examples/dreamcast/network/Makefile =================================================================== --- kos/examples/dreamcast/network/Makefile 2010-10-17 21:55:25 UTC (rev 684) +++ kos/examples/dreamcast/network/Makefile 2010-10-18 18:33:14 UTC (rev 685) @@ -8,18 +8,21 @@ $(KOS_MAKE) -C basic $(KOS_MAKE) -C httpd $(KOS_MAKE) -C ping + $(KOS_MAKE) -C ping6 # $(KOS_MAKE) -C dcload-ip-lwip-test clean: $(KOS_MAKE) -C basic clean $(KOS_MAKE) -C httpd clean $(KOS_MAKE) -C ping clean + $(KOS_MAKE) -C ping6 clean # $(KOS_MAKE) -C dcload-ip-lwip-test clean dist: $(KOS_MAKE) -C basic dist $(KOS_MAKE) -C httpd dist $(KOS_MAKE) -C ping dist + $(KOS_MAKE) -C ping6 dist # $(KOS_MAKE) -C dcload-ip-lwip-test dist Added: kos/examples/dreamcast/network/ping6/Makefile =================================================================== --- kos/examples/dreamcast/network/ping6/Makefile (rev 0) +++ kos/examples/dreamcast/network/ping6/Makefile 2010-10-18 18:33:14 UTC (rev 685) @@ -0,0 +1,32 @@ +# +# Basic KallistiOS skeleton / test program +# (c)2001 Dan Potter +# + +# Put the filename of the output binary here +TARGET = ping.elf + +# List all of your C files here, but change the extension to ".o" +OBJS = ping.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: + -rm -f $(TARGET) $(OBJS) + +rm-elf: + -rm -f $(TARGET) + +$(TARGET): $(OBJS) + $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ + $(OBJS) $(OBJEXTRA) $(KOS_LIBS) + +run: $(TARGET) + $(KOS_LOADER) $(TARGET) -n + +dist: + rm -f $(OBJS) + $(KOS_STRIP) $(TARGET) + Added: kos/examples/dreamcast/network/ping6/ping.c =================================================================== --- kos/examples/dreamcast/network/ping6/ping.c (rev 0) +++ kos/examples/dreamcast/network/ping6/ping.c 2010-10-18 18:33:14 UTC (rev 685) @@ -0,0 +1,73 @@ +/* KallistiOS ##version## + + ping6.c + Copyright (C) 2010 Lawrence Sebald + + This example is a very basic "ping6" program, much like you might find on + any computer. However, this version lacks many of the niceties you might find + on a real OS' ping program. + + This example also shows how to display things on the framebuffer with the + "fb" device for dbgio. + +*/ + +#include <stdio.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <arch/arch.h> +#include <kos/net.h> +#include <kos/thread.h> +#include <kos/dbgio.h> + +KOS_INIT_FLAGS(INIT_DEFAULT | INIT_NET); + +#define DATA_SIZE 56 + +int main(int argc, char *argv[]) { + /* The address to ping... */ + struct in6_addr addr; + uint8 data[DATA_SIZE]; + char str1[INET6_ADDRSTRLEN], str2[INET6_ADDRSTRLEN]; + int i; + + dbgio_dev_select("fb"); + + /* Set the address to ping. This corresponds to sylverant.net */ + inet_pton(AF_INET6, "2001:470:8:68d::1", &addr); + + /* Fill in the data for the ping packet... this is pretty simple and doesn't + really have any real meaning... */ + for(i = 0; i < DATA_SIZE; ++i) { + data[i] = (uint8)i; + } + + /* Send out a router solicitation so that we get a global prefix. */ + printf("Attempting to solicit a router\n"); + net_icmp6_send_rsol(net_default_dev); + thd_sleep(10000); + + if(!net_default_dev->ip6_addr_count) { + printf("Couldn't get a global prefix!\n"); + thd_sleep(2000); + return 0; + } + + inet_ntop(AF_INET6, &net_default_dev->ip6_addrs[0], str1, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &addr, str2, INET6_ADDRSTRLEN); + + printf("PING6 %s --> %s\n", str1, str2); + + /* Send out 10 pings, waiting 250ms between attempts. */ + for(i = 0; i < 2; ++i) { + net_icmp6_send_echo(net_default_dev, &addr, 0, i, data, DATA_SIZE); + thd_sleep(250); + } + + /* Wait 2 seconds for the user to see what's on the screen before we clear + it during the exit back to the loader */ + thd_sleep(10 * 1000); + + return 0; +} Modified: kos/include/kos/net.h =================================================================== --- kos/include/kos/net.h 2010-10-17 21:55:25 UTC (rev 684) +++ kos/include/kos/net.h 2010-10-18 18:33:14 UTC (rev 685) @@ -14,6 +14,7 @@ #include <arch/types.h> #include <sys/queue.h> +#include <netinet/in.h> /* All functions in this header return < 0 on failure, and 0 on success. */ @@ -23,97 +24,115 @@ centric, though I suppose you could stuff other things into this system like PPP. */ typedef struct knetif { - /* Device list handle */ - LIST_ENTRY(knetif) if_list; + /* Device list handle */ + LIST_ENTRY(knetif) if_list; - /* Device name ("bba", "la", etc) */ - const char *name; + /* Device name ("bba", "la", etc) */ + const char *name; - /* Long description of the device */ - const char *descr; + /* Long description of the device */ + const char *descr; - /* Unit index (starts at zero and counts upwards for multiple - network devices of the same type) */ - int index; + /* Unit index (starts at zero and counts upwards for multiple + network devices of the same type) */ + int index; - /* Internal device ID (for whatever the driver wants) */ - uint32 dev_id; + /* Internal device ID (for whatever the driver wants) */ + uint32 dev_id; - /* Interface flags */ - uint32 flags; + /* Interface flags */ + uint32 flags; - /* The device's MAC address */ - uint8 mac_addr[6]; + /* The device's MAC address */ + uint8 mac_addr[6]; - /* The device's IP address (if any) */ - uint8 ip_addr[4]; + /* The device's IP address (if any) */ + uint8 ip_addr[4]; - /* The device's netmask */ - uint8 netmask[4]; + /* The device's netmask */ + uint8 netmask[4]; - /* The device's gateway's IP address */ - uint8 gateway[4]; + /* The device's gateway's IP address */ + uint8 gateway[4]; - /* The device's broadcast address */ - uint8 broadcast[4]; + /* The device's broadcast address */ + uint8 broadcast[4]; - /* The device's DNS server address */ - uint8 dns[4]; + /* The device's DNS server address */ + uint8 dns[4]; - /* The interface's MTU */ - int mtu; + /* The device's MTU */ + int mtu; - /* All of the following callback functions should return a negative - value on failure, and a zero or positive value on success. Some - functions have special values, as noted. */ + /* The device's Link-local IPv6 address */ + struct in6_addr ip6_lladdr; - /* Attempt to detect the device */ - int (*if_detect)(struct knetif * self); + /* Any further IPv6 addresses the device has. The first address in this list + will always be used, unless otherwise specified */ + struct in6_addr *ip6_addrs; + int ip6_addr_count; - /* Initialize the device */ - int (*if_init)(struct knetif * self); + /* The device's gateway's IPv6 address */ + struct in6_addr ip6_gateway; - /* Shutdown the device */ - int (*if_shutdown)(struct knetif * self); + /* Default MTU over IPv6 and default hop count */ + uint32 mtu6; + int hop_limit; - /* Start the device (after init or stop) */ - int (*if_start)(struct knetif * self); + /* All of the following callback functions should return a negative + value on failure, and a zero or positive value on success. Some + functions have special values, as noted. */ - /* Stop (hibernate) the device */ - int (*if_stop)(struct knetif * self); + /* Attempt to detect the device */ + int (*if_detect)(struct knetif * self); - /* Queue a packet for transmission; see special return values - below the structure */ - int (*if_tx)(struct knetif * self, const uint8 * data, int len, int blocking); + /* Initialize the device */ + int (*if_init)(struct knetif * self); - /* Commit any queued output packets */ - int (*if_tx_commit)(struct knetif * self); + /* Shutdown the device */ + int (*if_shutdown)(struct knetif * self); - /* Poll for queued receive packets, if neccessary */ - int (*if_rx_poll)(struct knetif * self); + /* Start the device (after init or stop) */ + int (*if_start)(struct knetif * self); - /* Set flags; you should generally manipulate flags through here so that - the driver gets a chance to act on the info. */ - int (*if_set_flags)(struct knetif * self, uint32 flags_and, uint32 flags_or); + /* Stop (hibernate) the device */ + int (*if_stop)(struct knetif * self); + + /* Queue a packet for transmission; see special return values + below the structure */ + int (*if_tx)(struct knetif * self, const uint8 * data, int len, int blocking); + + /* Commit any queued output packets */ + int (*if_tx_commit)(struct knetif * self); + + /* Poll for queued receive packets, if neccessary */ + int (*if_rx_poll)(struct knetif * self); + + /* Set flags; you should generally manipulate flags through here so that + the driver gets a chance to act on the info. */ + int (*if_set_flags)(struct knetif * self, uint32 flags_and, uint32 flags_or); + + /* Set a device's multicast list */ + int (*if_set_mc)(struct knetif *self, const uint8 *list, int count); } netif_t; /* Flags for netif_t */ -#define NETIF_NO_FLAGS 0x00000000 -#define NETIF_REGISTERED 0x00000001 /* Is it registered? */ -#define NETIF_DETECTED 0x00000002 /* Is it detected? */ -#define NETIF_INITIALIZED 0x00000004 /* Has it been initialized? */ -#define NETIF_RUNNING 0x00000008 /* Has start() been called? */ -#define NETIF_PROMISC 0x00010000 /* Promiscuous mode */ -#define NETIF_NEEDSPOLL 0x01000000 /* Needs to be polled for input */ +#define NETIF_NO_FLAGS 0x00000000 +#define NETIF_REGISTERED 0x00000001 /* Is it registered? */ +#define NETIF_DETECTED 0x00000002 /* Is it detected? */ +#define NETIF_INITIALIZED 0x00000004 /* Has it been initialized? */ +#define NETIF_RUNNING 0x00000008 /* Has start() been called? */ +#define NETIF_PROMISC 0x00010000 /* Promiscuous mode */ +#define NETIF_NEEDSPOLL 0x01000000 /* Needs to be polled for input */ /* Return types for if_tx */ -#define NETIF_TX_OK 0 -#define NETIF_TX_ERROR -1 -#define NETIF_TX_AGAIN -2 +#define NETIF_TX_OK 0 +#define NETIF_TX_ERROR -1 +#define NETIF_TX_AGAIN -2 /* Blocking types */ -#define NETIF_NOBLOCK 0 -#define NETIF_BLOCK 1 +#define NETIF_NOBLOCK 0 +#define NETIF_BLOCK 1 /* Define the list type */ @@ -124,17 +143,17 @@ an IP address, and a timestamp from 'jiffies'. The timestamp allows aging and eventual removal. */ typedef struct netarp { - /* ARP cache list handle */ - LIST_ENTRY(netarp) ac_list; + /* ARP cache list handle */ + LIST_ENTRY(netarp) ac_list; - /* Mac address */ - uint8 mac[6]; + /* Mac address */ + uint8 mac[6]; - /* Associated IP address */ - uint8 ip[4]; + /* Associated IP address */ + uint8 ip[4]; - /* Cache entry time; if zero, this entry won't expire */ - uint32 timestamp; + /* Cache entry time; if zero, this entry won't expire */ + uint32 timestamp; } netarp_t; /* Define the list type */ @@ -222,12 +241,12 @@ /* IPv4 statistics structure. This structure holds some basic statistics about the IPv4 layer of the stack, and can be retrieved with the function below. */ typedef struct net_ipv4_stats { - uint32 pkt_sent; /* Packets sent out successfully */ - uint32 pkt_send_failed; /* Packets that failed to send */ - uint32 pkt_recv; /* Packets received successfully */ - uint32 pkt_recv_bad_size; /* Packets of a bad size */ - uint32 pkt_recv_bad_chksum; /* Packets with a bad checksum */ - uint32 pkt_recv_bad_proto; /* Packets with an unknown protocol */ + uint32 pkt_sent; /* Packets sent out successfully */ + uint32 pkt_send_failed; /* Packets that failed to send */ + uint32 pkt_recv; /* Packets received successfully */ + uint32 pkt_recv_bad_size; /* Packets of a bad size */ + uint32 pkt_recv_bad_chksum; /* Packets with a bad checksum */ + uint32 pkt_recv_bad_proto; /* Packets with an unknown protocol */ } net_ipv4_stats_t; /* Retrieve statistics from the IPv4 layer. */ @@ -241,17 +260,97 @@ individual bytes */ void net_ipv4_parse_address(uint32 addr, uint8 out[4]); +/***** net_icmp6.c ********************************************************/ + +/* Type of ping reply callback */ +typedef void (*net6_echo_cb)(const struct in6_addr *, uint16, uint64, uint8, + const uint8 *, int); + +/* Where will we handle possibly notifying the user of ping replies? */ +extern net6_echo_cb net_icmp6_echo_cb; + +/* Send an ICMPv6 Echo (PING6) packet to the specified device */ +int net_icmp6_send_echo(netif_t *net, const struct in6_addr *dst, uint16 ident, + uint16 seq, const uint8 *data, int size); + +/* Send a Neighbor Solicitation packet on the specified device */ +int net_icmp6_send_nsol(netif_t *net, const struct in6_addr *dst, + const struct in6_addr *target, int dupdet); + +/* Send a Neighbor Advertisement packet on the specified device */ +int net_icmp6_send_nadv(netif_t *net, const struct in6_addr *dst, + const struct in6_addr *target, int sol); + +/* Send a Router Solicitation request on the specified interface */ +int net_icmp6_send_rsol(netif_t *net); + +/* Destination Unreachable codes */ +#define ICMP6_DEST_UNREACH_NO_ROUTE 0 +#define ICMP6_DEST_UNREACH_PROHIBITED 1 +#define ICMP6_DEST_UNREACH_BEYOND_SCOPE 2 +#define ICMP6_DEST_UNREACH_ADDR_UNREACH 3 +#define ICMP6_DEST_UNREACH_PORT_UNREACH 4 +#define ICMP6_DEST_UNREACH_FAIL_EGRESS 5 +#define ICMP6_DEST_UNREACH_BAD_ROUTE 6 + +/* Time Exceeded codes */ +#define ICMP6_TIME_EXCEEDED_HOPS_EXC 0 +#define ICMP6_TIME_EXCEEDED_FRAGMENT 1 + +/* Parameter Problem codes */ +#define ICMP6_PARAM_PROB_BAD_HEADER 0 +#define ICMP6_PARAM_PROB_UNK_HEADER 1 +#define ICMP6_PARAM_PROB_UNK_OPTION 2 + +/***** net_ipv6.c *********************************************************/ + +/* IPv6 statistics structure. This structure holds some basic statistics about + the IPv6 layer of the stack, and can be retrieved with the function below. */ +typedef struct net_ipv6_stats { + uint32 pkt_sent; /* Packets sent out successfully */ + uint32 pkt_send_failed; /* Packets that failed to send */ + uint32 pkt_recv; /* Packets received successfully */ + uint32 pkt_recv_bad_size; /* Packets of a bad size */ + uint32 pkt_recv_bad_proto; /* Packets with an unknown protocol */ + uint32 pkt_recv_bad_ext; /* Packets with an unknown ext. header */ +} net_ipv6_stats_t; + +/* Retrieve statistics from the IPv6 layer. */ +net_ipv6_stats_t net_ipv6_get_stats(); + +/***** net_ndp.c **********************************************************/ + +/* Init */ +int net_ndp_init(); + +/* Shutdown */ +void net_ndp_shutdown(); + +/* Garbage collect timed out entries */ +void net_ndp_gc(); + +/* Add an entry to the NDP cache manually */ +int net_ndp_insert(netif_t *nif, const uint8 mac[6], const struct in6_addr *ip, + int unsol); + +/* Look up an entry from the NDP cache; if no entry is found, then an NDP + query will be sent and an error will be returned. If you specify a packet + with the call, it will be sent when the reply comes in. pkt should be a + simple IPv6 header, data anything that comes after it. */ +int net_ndp_lookup(netif_t *net, const struct in6_addr *ip, uint8 mac_out[6], + const void *pkt, const uint8 *data, int data_size); + /***** net_udp.c **********************************************************/ /* UDP statistics structure. This structure holds some basic statistics about the UDP layer of the stack, and can be retrieved with the function below. */ typedef struct net_udp_stats { - uint32 pkt_sent; /* Packets sent out successfully */ - uint32 pkt_send_failed; /* Packets that failed to send */ - uint32 pkt_recv; /* Packets received successfully */ - uint32 pkt_recv_bad_size; /* Packets of a bad size */ - uint32 pkt_recv_bad_chksum; /* Packets with a bad checksum */ - uint32 pkt_recv_no_sock; /* Packets with to an unopened socket */ + uint32 pkt_sent; /* Packets sent out successfully */ + uint32 pkt_send_failed; /* Packets that failed to send */ + uint32 pkt_recv; /* Packets received successfully */ + uint32 pkt_recv_bad_size; /* Packets of a bad size */ + uint32 pkt_recv_bad_chksum; /* Packets with a bad checksum */ + uint32 pkt_recv_no_sock; /* Packets with to an unopened socket */ } net_udp_stats_t; /* Retrieve statistics from the UDP layer. */ @@ -263,6 +362,31 @@ /* Shutdown */ void net_udp_shutdown(); +/***** net_crc.c **********************************************************/ + +/* Calculate a "little-endian" CRC-32 over a block of data. */ +uint32 net_crc32le(const uint8 *data, int size); + +/* Calculate a "big-endian" CRC-32 over a block of data. */ +uint32 net_crc32be(const uint8 *data, int size); + +/***** net_multicast.c ****************************************************/ + +/* Add a entry to our multicast list, autocommitting it to the network interface + in the process. */ +int net_multicast_add(const uint8 mac[6]); + +/* Delete an entry from our multicast list, autocommitting in the process. */ +int net_multicast_del(const uint8 mac[6]); + +/* Check if an address is on the multicast list. Returns 0 if the address is not + on the list, -1 on error, and 1 if the address is in the list. */ +int net_multicast_check(const uint8 mac[6]); + +/* Init / Shutdown */ +int net_multicast_init(); +void net_multicast_shutdown(); + /***** net_core.c *********************************************************/ /* Interface list; note: do not manipulate directly */ @@ -283,7 +407,6 @@ /* Unregister a network device */ int net_unreg_device(netif_t *device); - /* Init */ int net_init(); Modified: kos/kernel/arch/dreamcast/hardware/network/broadband_adapter.c =================================================================== --- kos/kernel/arch/dreamcast/hardware/network/broadband_adapter.c 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/arch/dreamcast/hardware/network/broadband_adapter.c 2010-10-18 18:33:14 UTC (rev 685) @@ -2,9 +2,9 @@ net/broadband_adapter.c - Copyright (C)2001,2003,2005 Dan Potter - Copyright (C)2004 Vincent Penne - Copyright (C)2007, 2008 Lawrence Sebald + Copyright (C) 2001,2003,2005 Dan Potter + Copyright (C) 2004 Vincent Penne + Copyright (C) 2007, 2008, 2010 Lawrence Sebald */ @@ -863,6 +863,21 @@ netif_t bba_if; +static void set_ipv6_lladdr() { + /* Set up the IPv6 link-local address. This is done in accordance with + Section 4/5 of RFC 2464 based on the MAC Address of the adapter. */ + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[0] = 0xFE; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[1] = 0x80; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[8] = bba_if.mac_addr[0] ^ 0x02; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[9] = bba_if.mac_addr[1]; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[10] = bba_if.mac_addr[2]; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[11] = 0xFF; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[12] = 0xFE; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[13] = bba_if.mac_addr[3]; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[14] = bba_if.mac_addr[4]; + bba_if.ip6_lladdr.__s6_addr.__s6_addr8[15] = bba_if.mac_addr[5]; +} + /* They only ever made one GAPS peripheral, so this should suffice */ static int bba_if_detect(netif_t *self) { if (bba_if.flags & NETIF_DETECTED) @@ -883,6 +898,7 @@ return -1; memcpy(bba_if.mac_addr, rtl.mac, 6); + set_ipv6_lladdr(); bba_if.flags |= NETIF_INITIALIZED; return 0; } @@ -994,6 +1010,41 @@ return 0; } +static int bba_if_set_mc(netif_t *self, const uint8 *list, int count) { + uint32 old; + + if(count == 0) { + /* Clear the multicast address filter */ + g2_write_32(NIC(RT_MAR0 + 0), 0); + g2_write_32(NIC(RT_MAR0 + 4), 0); + + /* Disable multicast reception */ + old = g2_read_32(NIC(RT_RXCONFIG)); + g2_write_32(NIC(RT_RXCONFIG), old & ~0x00000004); + } + else { + int i, pos; + uint32 tmp; + uint32 mar[2] = { 0, 0 }; + + /* Go through each entry and add the value to the filter */ + for(i = 0, pos = 0; i < count; ++i, pos += 6) { + tmp = net_crc32be(list + pos, 6) >> 26; + mar[tmp >> 5] |= (1 << (tmp & 0x1F)); + } + + /* Set the multicast address filter */ + g2_write_32(NIC(RT_MAR0 + 0), mar[0]); + g2_write_32(NIC(RT_MAR0 + 4), mar[1]); + + /* Enable multicast reception */ + old = g2_read_32(NIC(RT_RXCONFIG)); + g2_write_32(NIC(RT_RXCONFIG), old | 0x00000004); + } + + return 0; +} + /* We'll take packets from the interrupt handler and push them into netcore */ static void bba_if_netinput(uint8 *pkt, int pktsize) { net_input(&bba_if, pkt, pktsize); @@ -1049,6 +1100,12 @@ memset(bba_if.broadcast, 0, sizeof(bba_if.broadcast)); memset(bba_if.dns, 0, sizeof(bba_if.dns)); bba_if.mtu = 1500; /* The Ethernet v2 MTU */ + memset(&bba_if.ip6_lladdr, 0, sizeof(bba_if.ip6_lladdr)); + bba_if.ip6_addrs = NULL; + bba_if.ip6_addr_count = 0; + memset(&bba_if.ip6_gateway, 0, sizeof(bba_if.ip6_gateway)); + bba_if.mtu6 = 0; + bba_if.hop_limit = 0; bba_if.if_detect = bba_if_detect; bba_if.if_init = bba_if_init; bba_if.if_shutdown = bba_if_shutdown; @@ -1058,6 +1115,7 @@ bba_if.if_tx_commit = bba_if_tx_commit; bba_if.if_rx_poll = bba_if_rx_poll; bba_if.if_set_flags = bba_if_set_flags; + bba_if.if_set_mc = bba_if_set_mc; /* Attempt to set up our IP address et al from the flashrom */ bba_set_ispcfg(); Modified: kos/kernel/arch/dreamcast/hardware/network/lan_adapter.c =================================================================== --- kos/kernel/arch/dreamcast/hardware/network/lan_adapter.c 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/arch/dreamcast/hardware/network/lan_adapter.c 2010-10-18 18:33:14 UTC (rev 685) @@ -2,7 +2,8 @@ net/lan_adapter.c - (c)2002 Dan Potter + Copyright (C) 2002 Dan Potter + Copyright (C) 2010 Lawrence Sebald */ @@ -364,7 +365,7 @@ la_write(i + DLCR8, la_mac[i]); /* Clear the multicast address */ - for (i=0; i<6; i++) + for (i=0; i<8; i++) la_write(i + MAR8, 0); dbglog(DBG_DEBUG, "lan_adapter: MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -543,6 +544,21 @@ netif_t la_if; +static void set_ipv6_lladdr() { + /* Set up the IPv6 link-local address. This is done in accordance with + Section 4/5 of RFC 2464 based on the MAC Address of the adapter. */ + la_if.ip6_lladdr.__s6_addr.__s6_addr8[0] = 0xFE; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[1] = 0x80; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[8] = la_if.mac_addr[0] ^ 0x02; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[9] = la_if.mac_addr[1]; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[10] = la_if.mac_addr[2]; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[11] = 0xFF; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[12] = 0xFE; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[13] = la_if.mac_addr[3]; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[14] = la_if.mac_addr[4]; + la_if.ip6_lladdr.__s6_addr.__s6_addr8[15] = la_if.mac_addr[5]; +} + static int la_if_detect(netif_t * self) { if (self->flags & NETIF_DETECTED) return 0; @@ -562,6 +578,7 @@ return -1; memcpy(self->mac_addr, la_mac, 6); + set_ipv6_lladdr(); self->flags |= NETIF_INITIALIZED; return 0; } @@ -631,6 +648,43 @@ return 0; } +static int la_if_set_mc(netif_t *self, const uint8 *list, int count) { + int i; + + /* Reset Data Link Control */ + timer_spin_sleep(2); + la_write(DLCR6, la_read(DLCR6) | DLCR6_DLCRST); + timer_spin_sleep(2); + + if(count == 0) { + /* Clear the multicast address filter */ + for(i = 0; i < 8; i++) { + la_write(MAR8 + i, 0); + } + } + else { + int pos; + uint32 tmp; + uint8 mar[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + /* Go through each entry and add the value to the filter */ + for(i = 0, pos = 0; i < count; ++i, pos += 6) { + tmp = net_crc32le(list + pos, 6) >> 26; + mar[tmp >> 3] |= 1 << (tmp & 7); + } + + /* Set the multicast address filter */ + for(i = 0; i < 8; i++) { + la_write(MAR8 + i, mar[i]); + } + } + + /* Enable transmitter / receiver */ + la_write(DLCR6, (la_read(DLCR6) & ~DLCR6_DLCRST)); + + return 0; +} + /* Set ISP configuration from the flashrom, as long as we're configured staticly */ static void la_set_ispcfg() { flashrom_ispcfg_t isp; @@ -661,7 +715,7 @@ la_if.name = "la"; la_if.descr = "Lan Adapter (HIT-0300)"; la_if.index = 0; - la_if.dev_id = 0 ; + la_if.dev_id = 0; la_if.flags = NETIF_NO_FLAGS; memset(la_if.ip_addr, 0, sizeof(la_if.ip_addr)); memset(la_if.netmask, 0, sizeof(la_if.netmask)); @@ -669,6 +723,12 @@ memset(la_if.broadcast, 0, sizeof(la_if.broadcast)); memset(la_if.dns, 0, sizeof(la_if.dns)); la_if.mtu = 1500; /* The Ethernet v2 MTU */ + memset(&la_if.ip6_lladdr, 0, sizeof(la_if.ip6_lladdr)); + la_if.ip6_addrs = NULL; + la_if.ip6_addr_count = 0; + memset(&la_if.ip6_gateway, 0, sizeof(la_if.ip6_gateway)); + la_if.mtu6 = 0; + la_if.hop_limit = 0; la_if.if_detect = la_if_detect; la_if.if_init = la_if_init; la_if.if_shutdown = la_if_shutdown; @@ -678,6 +738,7 @@ la_if.if_tx_commit = la_if_tx_commit; la_if.if_rx_poll = la_if_rx_poll; la_if.if_set_flags = la_if_set_flags; + la_if.if_set_mc = la_if_set_mc; /* Attempt to set up our IP address et al from the flashrom */ la_set_ispcfg(); Modified: kos/kernel/net/Makefile =================================================================== --- kos/kernel/net/Makefile 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/net/Makefile 2010-10-18 18:33:14 UTC (rev 685) @@ -5,7 +5,8 @@ # OBJS = net_core.o net_arp.o net_input.o net_icmp.o net_ipv4.o net_udp.o -OBJS += net_dhcp.o net_ipv4_frag.o net_thd.o net_ipv6.o +OBJS += net_dhcp.o net_ipv4_frag.o net_thd.o net_ipv6.o net_icmp6.o net_crc.o +OBJS += net_ndp.o net_multicast.o SUBDIRS = include $(KOS_BASE)/Makefile.prefab Modified: kos/kernel/net/net_core.c =================================================================== --- kos/kernel/net/net_core.c 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/net/net_core.c 2010-10-18 18:33:14 UTC (rev 685) @@ -15,6 +15,7 @@ #include "net_dhcp.h" #include "net_thd.h" #include "net_ipv4.h" +#include "net_ipv6.h" /* @@ -143,6 +144,8 @@ /* Init */ int net_init() { + int rv = 0; + /* Make sure we haven't already done this */ if(net_initted) return 0; @@ -157,9 +160,18 @@ /* Initialize the ARP cache */ net_arp_init(); - /* Initialize IP fragmentation support */ + /* Initialize the NDP cache */ + net_ndp_init(); + + /* Initialize IPv4 fragmentation support */ net_ipv4_frag_init(); + /* Initialize multicast support */ + net_multicast_init(); + + /* Initialize IPv6 support */ + net_ipv6_init(); + /* Initialize the sockets-like interface */ fs_socket_init(); @@ -170,12 +182,12 @@ net_dhcp_init(); if(net_default_dev && !net_default_dev->ip_addr[0]) { - return net_dhcp_request(); + rv = net_dhcp_request(); } net_initted = 1; - return 0; + return rv; } /* Shutdown */ @@ -195,9 +207,18 @@ /* Shut down the sockets-like interface */ fs_socket_shutdown(); - /* Shut down IP fragmentation support */ + /* Shut down IPv6 support */ + net_ipv6_shutdown(); + + /* Shut down multicast support */ + net_multicast_shutdown(); + + /* Shut down IPv4 fragmentation support */ net_ipv4_frag_shutdown(); + /* Shut down the NDP cache */ + net_ndp_shutdown(); + /* Shut down the ARP cache */ net_arp_shutdown(); Added: kos/kernel/net/net_crc.c =================================================================== --- kos/kernel/net/net_crc.c (rev 0) +++ kos/kernel/net/net_crc.c 2010-10-18 18:33:14 UTC (rev 685) @@ -0,0 +1,49 @@ +/* KallistiOS ##version## + + kernel/net/net_crc.c + Copyright (C) 2009, 2010 Lawrence Sebald + +*/ + +#include <kos/net.h> + +/* Calculate a CRC-32 checksum over a given block of data. Somewhat inspired by + the CRC32 function in Figure 14-6 of http://www.hackersdelight.org/crc.pdf */ +uint32 net_crc32le(const uint8 *data, int size) { + int i; + uint32 rv = 0xFFFFFFFF; + + for(i = 0; i < size; ++i) { + rv ^= data[i]; + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + rv = (0xEDB88320 & (-(rv & 1))) ^ (rv >> 1); + } + + return ~rv; +} + +/* This one isn't quite as nice as the one above for little-endian... */ +uint32 net_crc32be(const uint8 *data, int size) { + int i, j; + uint32 rv = 0xFFFFFFFF, b, c; + + for(i = 0; i < size; ++i) { + b = data[i]; + + for(j = 0; j < 8; ++j) { + c = ((rv & 0x80000000) ? 1 : 0) ^ (b & 1); + b >>= 1; + + if(c) rv = ((rv << 1) ^ 0x04C11DB6) | c; + else rv <<= 1; + } + } + + return rv; +} Modified: kos/kernel/net/net_icmp.c =================================================================== --- kos/kernel/net/net_icmp.c 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/net/net_icmp.c 2010-10-18 18:33:14 UTC (rev 685) @@ -169,7 +169,7 @@ icmp = (icmp_hdr_t *)databuf; /* Fill in the ICMP Header */ - icmp->type = ICMP_MESSAGE_ECHO; /* Echo */ + icmp->type = ICMP_MESSAGE_ECHO; icmp->code = 0; icmp->checksum = 0; icmp->misc.m16[0] = htons(ident); Added: kos/kernel/net/net_icmp6.c =================================================================== --- kos/kernel/net/net_icmp6.c (rev 0) +++ kos/kernel/net/net_icmp6.c 2010-10-18 18:33:14 UTC (rev 685) @@ -0,0 +1,672 @@ +/* KallistiOS ##version## + + kernel/net/net_icmp6.c + Copyright (C) 2010 Lawrence Sebald + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arch/timer.h> + +#include "net_icmp6.h" +#include "net_ipv6.h" +#include "net_ipv4.h" /* For net_ipv4_checksum() */ + +/* +This file implements RFC 4443, the Internet Control Message Protocol for IPv6. +All messages mentioned below are from that RFC, unless otherwise specified. +Currently implemented message types are: + 128 - Echo + 129 - Echo Reply + 133 - Router Solicitation (RFC 4861) -- Sending only + 134 - Router Advertisement (RFC 4861) -- Receiving only + 135 - Neighbor Solicitation (RFC 4861) + 136 - Neighbor Advertisement (RFC 4861) + 137 - Redirect (RFC 4861) -- partial + +Message types that are not implemented yet (if ever): + 1 - Destination Unreachable + 2 - Packet Too Big + 3 - Time Exceeded + 4 - Parameter Problem + Any other numbers not listed in the first list... +*/ + +struct ping_pkt { + LIST_ENTRY(ping_pkt) pkt_list; + struct in6_addr ip; + uint8 *data; + int data_sz; + uint16 icmp_seq; + uint64 usec; +}; + +LIST_HEAD(ping_pkt_list, ping_pkt); + +static struct ping_pkt_list pings = LIST_HEAD_INITIALIZER(0); + +static void icmp6_default_echo_cb(const struct in6_addr *ip, uint16 seq, + uint64 delta_us, uint8 hlim, + const uint8 *data, int data_sz) { + char ipstr[INET6_ADDRSTRLEN]; + + printf("%d bytes from %s, icmp_seq=%d hlim=%d time=%.3f ms\n", data_sz, + inet_ntop(AF_INET6, ip, ipstr, INET6_ADDRSTRLEN), seq, hlim, + delta_us / 1000.0); +} + +/* The default echo (ping6) callback */ +net6_echo_cb net_icmp6_echo_cb = icmp6_default_echo_cb; + +/* Handle Echo Reply (ICMPv6 type 129) packets */ +static void net_icmp6_input_129(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + uint64 tmr; + struct ping_pkt *ping; + uint16 seq; + + tmr = timer_us_gettime64(); + seq = (d[7] | (d[6] << 8)); + + LIST_FOREACH(ping, &pings, pkt_list) { + if(ping->icmp_seq == seq) { + if(net_icmp6_echo_cb) { + net_icmp6_echo_cb(&ping->ip, seq, tmr - ping->usec, + ip->hop_limit, d, s); + } + + LIST_REMOVE(ping, pkt_list); + free(ping->data); + free(ping); + + return; + } + } +} + +/* Handle Echo (ICMPv6 type 128) packets */ +static void net_icmp6_input_128(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + uint16 cs; + struct in6_addr src, dst; + + memcpy(&src, &ip->dst_addr, sizeof(struct in6_addr)); + memcpy(&dst, &ip->src_addr, sizeof(struct in6_addr)); + + /* Set type to echo reply */ + icmp->type = ICMP6_MESSAGE_ECHO_REPLY; + + /* Invert the addresses and fix the hop limit */ + if(IN6_IS_ADDR_MC_LINKLOCAL(&src)) { + src = net->ip6_lladdr; + } + + ip->src_addr = src; + ip->dst_addr = dst; + + if(net->hop_limit) { + ip->hop_limit = net->hop_limit; + } + else { + ip->hop_limit = 255; + } + + /* Recompute the ICMP header checksum */ + icmp->checksum = 0; + cs = net_ipv6_checksum_pseudo(&src, &dst, ntohs(ip->length), IPV6_HDR_ICMP); + icmp->checksum = net_ipv4_checksum((uint8 *)icmp, ntohs(ip->length), cs); + + /* Send the result away */ + net_ipv6_send_packet(net, ip, d, s); +} + +static void dupdet(netif_t *net, const struct in6_addr *ip) { + struct in6_addr dst = *ip; + + /* Send to the solicited nodes multicast group for the specified addr */ + dst.s6_addr[0] = 0xFF; + dst.s6_addr[1] = 0x02; + dst.__s6_addr.__s6_addr16[1] = 0x0000; + dst.__s6_addr.__s6_addr16[2] = 0x0000; + dst.__s6_addr.__s6_addr16[3] = 0x0000; + dst.__s6_addr.__s6_addr16[4] = 0x0000; + dst.s6_addr[10] = 0x00; + dst.s6_addr[11] = 0x01; + dst.s6_addr[12] = 0xFF; + + net_icmp6_send_nsol(net, &dst, ip, 1); +} + +/* Handle Router Advertisement (ICMPv6 type 134) packets */ +static void net_icmp6_input_134(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + icmp6_router_adv_t *pkt = (icmp6_router_adv_t *)icmp; + struct in6_addr src; + uint16 len = ntohs(ip->length); + int pos = 0; + + /* Ignore obviously bad packets */ + if(len <= sizeof(icmp6_router_adv_t)) { + return; + } + + /* Make sure that the source address is link-local */ + memcpy(&src, &ip->src_addr, sizeof(struct in6_addr)); + if(!IN6_IS_ADDR_LINKLOCAL(&src)) { + return; + } + + /* Make sure the hop limit and code are correct */ + if(ip->hop_limit != 255 || pkt->code) { + return; + } + + /* If this router isn't default, we don't care about it at all. */ + if(!pkt->router_lifetime) { + return; + } + + /* If this router isn't the first one, then ignore it */ + if(net->ip6_gateway.s6_addr[0]) { + return; + } + + /* Parse the options that are in the advertisement */ + while(pos + sizeof(icmp6_router_adv_t) < len) { + /* Make sure the option is at least sane */ + if(!pkt->options[pos + 1]) { + return; + } + + switch(pkt->options[pos]) { + case NDP_OPT_MTU: + net->mtu6 = (pkt->options[pos + 4] << 24) | + (pkt->options[pos + 5] << 16) | + (pkt->options[pos + 6] << 8) | (pkt->options[pos + 7]); + break; + + case NDP_OPT_PREFIX_INFO: + { + icmp6_ndp_prefix_t *pfx = + (icmp6_ndp_prefix_t *)&pkt->options[pos]; + void *tmp; + struct in6_addr addr; + int i; + + /* Make sure the option is of the right length */ + if(pfx->length != 4) { + break; + } + + /* Make sure the prefix is of an appropriate length */ + if(pfx->prefix_length != 64) { + break; + } + + /* Make sure we have the on-link and autonomous flags set */ + if((pfx->flags & 0xC0) != 0xC0) { + break; + } + + /* Make sure we don't already have the prefix. */ + memcpy(&addr, &pfx->prefix, 8); + memcpy(&addr.s6_addr[8], &net->ip6_lladdr.s6_addr[8], 8); + + for(i = 0; i < net->ip6_addr_count; ++i) { + if(!memcmp(&addr, &net->ip6_addrs[i], + sizeof(struct in6_addr))) { + goto out; + } + } + + /* TODO: Handle preferred/valid lifetimes properly */ + /* Add the new address to our list */ + tmp = realloc(net->ip6_addrs, (net->ip6_addr_count + 1) * + sizeof(struct in6_addr)); + if(!tmp) { + break; + } + + net->ip6_addrs = (struct in6_addr *)tmp; + memcpy(&net->ip6_addrs[net->ip6_addr_count], &addr, + sizeof(struct in6_addr)); + + ++net->ip6_addr_count; + + dupdet(net, &addr); +out: + break; + } + + case NDP_OPT_SOURCE_LINK_ADDR: + { + icmp6_nsol_lladdr_t *ll = + (icmp6_nsol_lladdr_t *)&pkt->options[pos]; + + /* Make sure the length is sane */ + if(ll->length != 1) { + break; + } + + net_ndp_insert(net, ll->mac, &src, 1); + break; + } + } + + pos += pkt->options[pos + 1] << 3; + } + + memcpy(&net->ip6_gateway, &src, sizeof(struct in6_addr)); + net->hop_limit = pkt->cur_hop_limit; +} + +/* Handle Neighbor Solicitation (ICMPv6 type 135) packets */ +static void net_icmp6_input_135(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + icmp6_neighbor_sol_t *pkt = (icmp6_neighbor_sol_t *)icmp; + icmp6_nsol_lladdr_t *ll; + uint16 len = ntohs(ip->length); + struct in6_addr target, src; + int sol = 1, pos = 0, i; + + /* Ignore obviously bad packets */ + if(len < sizeof(icmp6_neighbor_sol_t)) { + return; + } + + /* Ignore neighbor solicitations for multicast addresses and ones that have + a hop limit that's wrong */ + memcpy(&target, &pkt->target, sizeof(struct in6_addr)); + + if(ip->hop_limit != 255 || IN6_IS_ADDR_MULTICAST(&target) || icmp->code) { + return; + } + + /* Make sure they're asking about this machine. */ + if(!memcmp(&target, &net->ip6_lladdr, sizeof(struct in6_addr))) { + goto cont; + } + + /* Check all non link-local prefixes we have */ + for(i = 0; i < net->ip6_addr_count; ++i) { + if(!memcmp(&target, &net->ip6_addrs[i], sizeof(struct in6_addr))) { + goto cont; + } + } + + /* If we get here, we haven't found it, so assume its not for us */ + return; + +cont: + /* Copy out the source address */ + memcpy(&src, &ip->src_addr, sizeof(struct in6_addr)); + + if(IN6_IS_ADDR_UNSPECIFIED(&src)) { + src = in6addr_linklocal_allnodes; + sol = 0; + } + /* If its not unspecified, see if there's a link-layer address option */ + else { + while(pos + sizeof(icmp6_neighbor_sol_t) < len) { + /* Make sure the option is at least sane */ + if(!pkt->options[pos + 1]) { + return; + } + + if(pkt->options[pos] == NDP_OPT_SOURCE_LINK_ADDR) { + ll = (icmp6_nsol_lladdr_t *)&pkt->options[pos]; + net_ndp_insert(net, ll->mac, &src, 1); + } + + pos += pkt->options[pos + 1] << 3; + } + } + + /* Send the neighbor advertisement */ + net_icmp6_send_nadv(net, &src, &target, sol); +} + +/* Handle Neighbor Advertisement (ICMPv6 type 136) packets */ +static void net_icmp6_input_136(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + icmp6_neighbor_adv_t *pkt = (icmp6_neighbor_adv_t *)icmp; + icmp6_nsol_lladdr_t *lladdr = (icmp6_nsol_lladdr_t *)pkt->options; + uint16 len = ntohs(ip->length); + struct in6_addr target, dest; + uint32 flags; + + /* Ignore obviously bad packets */ + if(len < sizeof(icmp6_neighbor_adv_t)) { + return; + } + + /* Silently drop packets that don't have the neighbor's lower level addr */ + if(len < sizeof(icmp6_neighbor_adv_t) + sizeof(icmp6_nsol_lladdr_t)) { + return; + } + + /* If the option isn't the target link layer address option, ignore it */ + if(lladdr->type != NDP_OPT_TARGET_LINK_ADDR || lladdr->length != 1) { + return; + } + + /* Make sure the hop limit is right and this isn't a multicast addr */ + memcpy(&target, &pkt->target, sizeof(struct in6_addr)); + if(ip->hop_limit != 255 || IN6_IS_ADDR_MULTICAST(&target)) { + return; + } + + /* Make sure if the destination is multicast, the solicited flag is zero */ + memcpy(&dest, &ip->dst_addr, sizeof(struct in6_addr)); + flags = pkt->flags; + if(IN6_IS_ADDR_MULTICAST(&dest) && (flags & 0x02)) { + return; + } + + net_ndp_insert(net, lladdr->mac, &target, !(flags & 0x02)); +} + +static void net_icmp6_input_137(netif_t *net, ipv6_hdr_t *ip, icmp6_hdr_t *icmp, + const uint8 *d, int s) { + icmp6_redirect_t *pkt = (icmp6_redirect_t *)icmp; + icmp6_nsol_lladdr_t *ll = (icmp6_nsol_lladdr_t *)pkt->options; + struct in6_addr target, dest; + char str[INET6_ADDRSTRLEN], str2[INET6_ADDRSTRLEN]; + int len = ntohs(ip->length), pos = 0; + + /* Reject obviously bad packets */ + if(len < sizeof(icmp6_redirect_t)) { + return; + } + + /* Copy out the addresses */ + memcpy(&target, &pkt->target, sizeof(struct in6_addr)); + memcpy(&dest, &pkt->dest, sizeof(struct in6_addr)); + + dbglog(DBG_KDEBUG, "net_icmp6: Redirect:\n" + "%s -> %s\n", inet_ntop(AF_INET6, &dest, str, INET6_ADDRSTRLEN), + inet_ntop(AF_INET6, &target, str2, INET6_ADDRSTRLEN)); + + /* Check the target and destination for equality -- if they're equal, update + the NDP entry and move on. */ + if(!memcmp(&target, &dest, sizeof(struct in6_addr))) { + while(pos + sizeof(icmp6_redirect_t) < len) { + /* Make sure the option is at least sane */ + if(!pkt->options[pos + 1]) { + return; + } + + if(pkt->options[pos] == NDP_OPT_TARGET_LINK_ADDR) { + ll = (icmp6_nsol_lladdr_t *)&pkt->options[pos]; + net_ndp_insert(net, ll->mac, &target, 0); + } + + pos += pkt->options[pos + 1] << 3; + } + } +} + +int net_icmp6_input(netif_t *net, ipv6_hdr_t *ip, const uint8 *d, int s) { + icmp6_hdr_t *icmp; + uint16 cs = net_ipv6_checksum_pseudo(&ip->src_addr, &ip->dst_addr, + ntohs(ip->length), IPV6_HDR_ICMP); + int i; + + /* Find the ICMPv6 header */ + icmp = (icmp6_hdr_t *)d; + + /* Check the checksum */ + i = net_ipv4_checksum(d, s, cs); + + if(i) { + dbglog(DBG_KDEBUG, "net_icmp6: icmp with invalid checksum\n"); + return -1; + } + + switch(icmp->type) { + case ICMP6_MESSAGE_ECHO: + net_icmp6_input_128(net, ip, icmp, d, s); + break; + + case ICMP6_MESSAGE_ECHO_REPLY: + net_icmp6_input_129(net, ip, icmp, d, s); + break; + + case ICMP6_ROUTER_ADVERTISEMENT: + net_icmp6_input_134(net, ip, icmp, d, s); + break; + + case ICMP6_NEIGHBOR_SOLICITATION: + net_icmp6_input_135(net, ip, icmp, d, s); + break; + + case ICMP6_NEIGHBOR_ADVERTISEMENT: + net_icmp6_input_136(net, ip, icmp, d, s); + break; + + case ICMP6_REDIRECT: + net_icmp6_input_137(net, ip, icmp, d, s); + break; + + default: + dbglog(DBG_KDEBUG, "net_icmp6: unknown icmp6 type: %d\n", + icmp->type); + } + + return 0; +} + +/* Send an ICMPv6 Echo (PING6) packet to the specified device */ +int net_icmp6_send_echo(netif_t *net, const struct in6_addr *dst, uint16 ident, + uint16 seq, const uint8 *data, int size) { + icmp6_echo_hdr_t *echo; + struct ping_pkt *newping; + uint8 databuf[sizeof(icmp6_hdr_t) + size + 4]; + struct in6_addr src; + uint16 cs; + + if(!net) { + if(!(net = net_default_dev)) { + return -1; + } + } + + /* If we're sending to the loopback, set that as our source too */ + if(IN6_IS_ADDR_LOOPBACK(dst)) { + src = in6addr_loopback; + } + else if(IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MC_LINKLOCAL(dst)) { + src = net->ip6_lladdr; + } + else if(net->ip6_addr_count) { + src = net->ip6_addrs[0]; + } + else { + return -1; + } + + echo = (icmp6_echo_hdr_t *)databuf; + + /* Fill in the ICMP Header */ + echo->type = ICMP6_MESSAGE_ECHO; + echo->code = 0; + echo->checksum = 0; + echo->ident = htons(ident); + echo->seq = htons(seq); + memcpy(databuf + sizeof(icmp6_echo_hdr_t), data, size); + + /* Compute the ICMP Checksum */ + cs = net_ipv6_checksum_pseudo(&src, dst, sizeof(icmp6_echo_hdr_t) + size, + IPV6_HDR_ICMP); + echo->checksum = net_ipv4_checksum(databuf, sizeof(icmp6_echo_hdr_t) + size, + cs); + + newping = (struct ping_pkt *) malloc(sizeof(struct ping_pkt)); + newping->data = (uint8 *)malloc(size); + newping->data_sz = size; + newping->icmp_seq = seq; + memcpy(newping->data, data, size); + newping->ip = *dst; + LIST_INSERT_HEAD(&pings, newping, pkt_list); + + newping->usec = timer_us_gettime64(); + return net_ipv6_send(net, databuf, sizeof(icmp6_echo_hdr_t) + size, 0, + IPV6_HDR_ICMP, &src, dst); +} + +/* Send a Neighbor Solicitation packet on the specified device */ +int net_icmp6_send_nsol(netif_t *net, const struct in6_addr *dst, + const struct in6_addr *target, int dupdet) { + icmp6_neighbor_sol_t *pkt; + icmp6_nsol_lladdr_t *ll; + uint8 databuf[sizeof(icmp6_neighbor_sol_t) + sizeof(icmp6_nsol_lladdr_t)]; + struct in6_addr src; + int size = sizeof(icmp6_neighbor_sol_t); + uint16 cs; + + if(!net) { + if(!(net = net_default_dev)) { + return -1; + } + } + + /* If we don't have a link-local address and we're not doing duplicate + detection, bail out now. */ + if(!net->ip6_lladdr.__s6_addr.__s6_addr8[0] && !dupdet) { + return -1; + } + + pkt = (icmp6_neighbor_sol_t *)databuf; + + /* Fill in the ICMP Header */ + pkt->type = ICMP6_NEIGHBOR_SOLICITATION; + pkt->code = 0; + pkt->checksum = 0; + pkt->reserved = 0; + memcpy(&pkt->target, target, sizeof(struct in6_addr)); + + /* If we're doing duplicate detection, send this on the unspecified address, + otherwise, on the link-local address. Also, if we're not doing duplicate + detection, add a neighbor solicitation link-layer address option. */ + if(dupdet) { + src = in6addr_any; + } + else { + if(IN6_IS_ADDR_LINKLOCAL(target)) { + src = net->ip6_lladdr; + } + else if(net->ip6_addr_count) { + src = net->ip6_addrs[0]; + } + else { + return -1; + } + + ll = (icmp6_nsol_lladdr_t *)(databuf + sizeof(icmp6_neighbor_sol_t)); + ll->type = NDP_OPT_SOURCE_LINK_ADDR; + ll->length = 1; + memcpy(ll->mac, net->mac_addr, 6); + size += sizeof(icmp6_nsol_lladdr_t); + } + + /* Compute the ICMP Checksum */ + cs = net_ipv6_checksum_pseudo(&src, dst, size, IPV6_HDR_ICMP); + pkt->checksum = net_ipv4_checksum(databuf, size, cs); + + return net_ipv6_send(net, databuf, size, 255, IPV6_HDR_ICMP, &src, dst); +} + +/* Send a Neighbor Advertisement packet on the specified device */ +int net_icmp6_send_nadv(netif_t *net, const struct in6_addr *dst, + const struct in6_addr *target, int sol) { + icmp6_neighbor_adv_t *pkt; + icmp6_nsol_lladdr_t *ll; + uint8 databuf[sizeof(icmp6_neighbor_adv_t) + sizeof(icmp6_nsol_lladdr_t)]; + struct in6_addr src; + int size = sizeof(icmp6_neighbor_adv_t) + sizeof(icmp6_nsol_lladdr_t); + uint16 cs; + + if(!net) { + if(!(net = net_default_dev)) { + return -1; + } + } + + pkt = (icmp6_neighbor_adv_t *)databuf; + + /* Fill in the ICMP Header */ + pkt->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + pkt->code = 0; + pkt->checksum = 0; + pkt->reserved[0] = pkt->reserved[1] = pkt->reserved[2] = 0; + pkt->flags = 0x40; /* Set the override flag */ + memcpy(&pkt->target, target, sizeof(struct in6_addr)); + + /* If this is a solicited request, handle it a little bit differently. */ + if(sol) { + pkt->flags |= 0x20; /* Set the solicited flag */ + } + + memcpy(&src, target, sizeof(struct in6_addr)); + + ll = (icmp6_nsol_lladdr_t *)(databuf + sizeof(icmp6_neighbor_adv_t)); + ll->type = NDP_OPT_TARGET_LINK_ADDR; + ll->length = 1; + memcpy(ll->mac, net->mac_addr, 6); + + /* Compute the ICMP Checksum */ + cs = net_ipv6_checksum_pseudo(&src, dst, size, IPV6_HDR_ICMP); + pkt->checksum = net_ipv4_checksum(databuf, size, cs); + + return net_ipv6_send(net, databuf, size, 255, IPV6_HDR_ICMP, &src, dst); +} + +/* Send a Router Solicitation request on the specified interface */ +int net_icmp6_send_rsol(netif_t *net) { + icmp6_router_sol_t *pkt; + icmp6_nsol_lladdr_t *ll; + uint8 databuf[sizeof(icmp6_router_sol_t) + sizeof(icmp6_nsol_lladdr_t)]; + struct in6_addr src; + int size = sizeof(icmp6_router_sol_t) + sizeof(icmp6_nsol_lladdr_t); + uint16 cs; + + if(!net) { + if(!(net = net_default_dev)) { + return -1; + } + } + + pkt = (icmp6_router_sol_t *)databuf; + + /* Fill in the ICMP Header */ + pkt->type = ICMP6_ROUTER_SOLICITATION; + pkt->code = 0; + pkt->checksum = 0; + pkt->reserved = 0; + + src = net->ip6_lladdr; + + /* If we're working on an unspecified address, then we don't include the + source link layer address option */ + if(IN6_IS_ADDR_UNSPECIFIED(&src)) { + size -= sizeof(icmp6_nsol_lladdr_t); + } + else { + ll = (icmp6_nsol_lladdr_t *)pkt->options; + ll->type = NDP_OPT_SOURCE_LINK_ADDR; + ll->length = 1; + memcpy(ll->mac, net->mac_addr, 6); + } + + /* Compute the ICMP Checksum */ + cs = net_ipv6_checksum_pseudo(&src, &in6addr_linklocal_allrouters, size, + IPV6_HDR_ICMP); + pkt->checksum = net_ipv4_checksum(databuf, size, cs); + + return net_ipv6_send(net, databuf, size, 255, IPV6_HDR_ICMP, &src, + &in6addr_linklocal_allrouters); +} Added: kos/kernel/net/net_icmp6.h =================================================================== --- kos/kernel/net/net_icmp6.h (rev 0) +++ kos/kernel/net/net_icmp6.h 2010-10-18 18:33:14 UTC (rev 685) @@ -0,0 +1,169 @@ +/* KallistiOS ##version## + + kernel/net/net_icmp6.h + Copyright (C) 2010 Lawrence Sebald + +*/ + +#ifndef __LOCAL_NET_ICMP6_H +#define __LOCAL_NET_ICMP6_H + +#include <kos/net.h> +#include "net_ipv6.h" + +#ifdef PACKED +#undef PACKED +#endif + +#define PACKED __attribute__((packed)) + +typedef struct icmp6_hdr_s { + uint8 type; + uint8 code; + uint16 checksum; +} PACKED icmp6_hdr_t; + +/* Header for Destination Unreachable packets (type 1) */ +typedef struct icmp6_dest_unreach_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 reserved; +} PACKED icmp6_dest_unreach_t; + +/* Header for Packet Too Big packets (type 2) */ +typedef struct icmp6_pkt_too_big_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 mtu; +} PACKED icmp6_pkt_too_big_t; + +/* Header for Time Exceeded packets (type 3) */ +typedef struct icmp6_time_exceeded_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 unused; +} PACKED icmp6_time_exceeded_t; + +/* Header for Parameter Problem packets (type 4) */ +typedef struct icmp6_param_problem_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 ptr; +} PACKED icmp6_param_problem_t; + +/* Header for Echo/Echo Reply packets (types 128/129) */ +typedef struct icmp6_echo_hdr_s { + uint8 type; + uint8 code; + uint16 checksum; + uint16 ident; + uint16 seq; +} PACKED icmp6_echo_hdr_t; + +/* Format for Router Solicitation packets (type 133) - RFC 4861 */ +typedef struct icmp6_router_sol_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 reserved; + uint8 options[]; +} PACKED icmp6_router_sol_t; + +/* Format for Router Advertisement packets (type 134) - RFC 4861 */ +typedef struct icmp6_router_adv_s { + uint8 type; + uint8 code; + uint16 checksum; + uint8 cur_hop_limit; + uint8 flags; + uint16 router_lifetime; + uint32 reachable_time; + uint32 retrans_timer; + uint8 options[]; +} PACKED icmp6_router_adv_t; + +/* Format for Neighbor Solicitation packets (type 135) - RFC 4861 */ +typedef struct icmp6_neighbor_sol_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 reserved; + struct in6_addr target; + uint8 options[]; +} PACKED icmp6_neighbor_sol_t; + +/* Format for Neighbor Advertisement packets (type 136) - RFC 4861 */ +typedef struct icmp6_neighbor_adv_s { + uint8 type; + uint8 code; + uint16 checksum; + uint8 flags; + uint8 reserved[3]; + struct in6_addr target; + uint8 options[]; +} PACKED icmp6_neighbor_adv_t; + +/* Link-layer address option for neighbor advertisement/solictation packets for + ethernet. */ +typedef struct icmp6_nsol_lladdr_s { + uint8 type; + uint8 length; + uint8 mac[6]; +} PACKED icmp6_nsol_lladdr_t; + +/* Redirect packet (type 137) - RFC 4861 */ +typedef struct icmp6_redirect_s { + uint8 type; + uint8 code; + uint16 checksum; + uint32 reserved; + struct in6_addr target; + struct in6_addr dest; + uint8 options[]; +} PACKED icmp6_redirect_t; + +/* Prefix information for router advertisement packets */ +typedef struct icmp6_ndp_prefix_s { + uint8 type; + uint8 length; + uint8 prefix_length; + uint8 flags; + uint32 valid_time; + uint32 preferred_time; + uint32 reserved; + struct in6_addr prefix; +} PACKED icmp6_ndp_prefix_t; + +#undef PACKED + +/* ICMPv6 Message types */ +/* Error messages (type < 127) */ +#define ICMP6_MESSAGE_DEST_UNREACHABLE 1 +#define ICMP6_MESSAGE_PKT_TOO_BIG 2 +#define ICMP6_MESSAGE_TIME_EXCEEDED 3 +#define ICMP6_MESSAGE_PARAM_PROBLEM 4 + +/* Informational messages (127 < type < 255) */ +#define ICMP6_MESSAGE_ECHO 128 +#define ICMP6_MESSAGE_ECHO_REPLY 129 + +/* Neighbor Discovery Protocol (RFC 4861) */ +#define ICMP6_ROUTER_SOLICITATION 133 +#define ICMP6_ROUTER_ADVERTISEMENT 134 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 +#define ICMP6_REDIRECT 137 /* Not supported */ + +#define NDP_OPT_SOURCE_LINK_ADDR 1 +#define NDP_OPT_TARGET_LINK_ADDR 2 +#define NDP_OPT_PREFIX_INFO 3 +#define NDP_OPT_REDIRECTED_HDR 4 +#define NDP_OPT_MTU 5 + +int net_icmp6_input(netif_t *src, ipv6_hdr_t *ih, const uint8 *data, int size); + +#endif /* !__LOCAL_NET_ICMP6_H */ Modified: kos/kernel/net/net_input.c =================================================================== --- kos/kernel/net/net_input.c 2010-10-17 21:55:25 UTC (rev 684) +++ kos/kernel/net/net_input.c 2010-10-18 18:33:14 UTC (rev 685) @@ -8,6 +8,7 @@ #include <stdio.h> #include <kos/net.h> #include "net_ipv4.h" +#include "net_ipv6.h" /* @@ -16,19 +17,32 @@ */ static int net_default_input(netif_t *nif, const uint8 *data, int len) { - uint16 proto = (uint16)((data[12] << 8) | (data[13])); + uint16 proto = (uint16)((data[12] << 8) | (data[13])); - switch(proto) { - case 0x0800: - return net_ipv4_input(nif, data + sizeof(eth_hdr_t), + /* If this is bound for a multicast address, make sure we actually care + about the one that it gets sent to. */ + if((data[0] & 0x01) && + (data[0] != 0xFF || data[1] != 0xFF || data[2] != 0xFF || + data[3] != 0xFF || data[4] != 0xFF || data[5] != 0xFF) && + !net_multicast_check(data)) { + return 0; + } + + switch(proto) { + case 0x0800: + return net_ipv4_input(nif, data + sizeof(eth_hdr_t), len - sizeof(eth_hdr_t)); - case 0x0806: - return net_arp_input(nif, data, len); + case 0x0806: + return net_arp_input(nif, data, len); - default: - return 0; - } + case 0x86DD: + return net_ipv6_input(nif, data + sizeof(eth_hdr_t), + len - sizeof(eth_hdr_t)); + + default: + return 0; + } } /* Where will input packets be routed? */ @@ -36,15 +50,15 @@ /* Process an incoming packet */ int net_input(netif_t *device, const uint8 *data, int len) { - if (net_input_target != NULL) - return net_input_target(device, data, len); - els... [truncated message content] |
From: <ljs...@us...> - 2010-10-17 21:55:33
|
Revision: 684 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=684&view=rev Author: ljsebald Date: 2010-10-17 21:55:25 +0000 (Sun, 17 Oct 2010) Log Message: ----------- Clean up warnings on some of the IN6_IS_ADDR_* macros, and fix a few others so they actually work. Modified Paths: -------------- kos/include/netinet/in.h Modified: kos/include/netinet/in.h =================================================================== --- kos/include/netinet/in.h 2010-10-16 01:55:42 UTC (rev 683) +++ kos/include/netinet/in.h 2010-10-17 21:55:25 UTC (rev 684) @@ -250,7 +250,8 @@ \return Nonzero if the address is link-local, 0 otherwise. */ #define IN6_IS_ADDR_LINKLOCAL(a) \ - (((a)->__s6_addr.__s6_addr16[0] & 0xFFC0) == 0xFE80) + (((a)->__s6_addr.__s6_addr8[0] == 0xFE) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0xC0) == 0x80)) /** \brief Test if an IPv6 Address is a site-local address. @@ -261,8 +262,8 @@ \return Nonzero if the address is site-local, 0 otherwise. */ #define IN6_IS_ADDR_SITELOCAL(a) \ - (((a)->__s6_addr.__s6_addr16[0] & 0xFFC0) == 0xFEC0) - + (((a)->__s6_addr.__s6_addr8[0] == 0xFE) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0xC0) == 0xC0)) /** \brief Test if an IPv6 Address is a multicast address. This macro tests whether an IPv6 address (struct in6_addr *) is a multicast @@ -284,8 +285,8 @@ address, 0 otherwise. */ #define IN6_IS_ADDR_MC_NODELOCAL(a) \ - IN6_IS_ADDR_MULTICAST(a) && \ - (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x01) + (IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x01)) /** \brief Test if an IPv6 Address is a link-local multicast address. @@ -297,8 +298,8 @@ address, 0 otherwise. */ #define IN6_IS_ADDR_MC_LINKLOCAL(a) \ - IN6_IS_ADDR_MULTICAST(a) && \ - (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x02) + (IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x02)) /** \brief Test if an IPv6 Address is a site-local multicast address. @@ -310,8 +311,8 @@ address, 0 otherwise. */ #define IN6_IS_ADDR_MC_SITELOCAL(a) \ - IN6_IS_ADDR_MULTICAST(a) && \ - (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x05) + (IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x05)) /** \brief Test if an IPv6 Address is an organization-local multicast address. @@ -323,8 +324,8 @@ multicast address, 0 otherwise. */ #define IN6_IS_ADDR_MC_ORGLOCAL(a) \ - IN6_IS_ADDR_MULTICAST(a) && \ - (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x08) + (IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x08)) /** \brief Test if an IPv6 Address is a global multicast address. @@ -336,8 +337,8 @@ 0 otherwise. */ #define IN6_IS_ADDR_MC_GLOBAL(a) \ - IN6_IS_ADDR_MULTICAST(a) && \ - (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x0E) + (IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x0E)) __END_DECLS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-16 01:55:48
|
Revision: 683 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=683&view=rev Author: ljsebald Date: 2010-10-16 01:55:42 +0000 (Sat, 16 Oct 2010) Log Message: ----------- Add the rest of the IN6_IS_ADDR_* macros to <netinet/in.h> from IEEE 1003.1-2008. Modified Paths: -------------- kos/include/netinet/in.h Modified: kos/include/netinet/in.h =================================================================== --- kos/include/netinet/in.h 2010-10-16 01:53:20 UTC (rev 682) +++ kos/include/netinet/in.h 2010-10-16 01:55:42 UTC (rev 683) @@ -187,8 +187,8 @@ This macro tests whether an IPv6 address (struct in6_addr *) is an unspecified address. - \param a The address to test (struct in6_addr *) - \return Nonzero if the address is unspecified, 0 otherwise. + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is unspecified, 0 otherwise. */ #define IN6_IS_ADDR_UNSPECIFIED(a) \ ((a)->__s6_addr.__s6_addr32[0] == 0 && \ @@ -201,8 +201,8 @@ This macro tests whether an IPv6 address (struct in6_addr *) is a loopback address. - \param a The address to test (struct in6_addr *) - \return Nonzero if the address is a loopback, 0 otherwise. + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a loopback, 0 otherwise. */ #define IN6_IS_ADDR_LOOPBACK(a) \ ((a)->__s6_addr.__s6_addr32[0] == 0 && \ @@ -217,8 +217,8 @@ This macro tests whether an IPv6 address (struct in6_addr *) is an IPv4 mapped address. - \param a The address to test (struct in6_addr *) - \return Nonzero if the address is IPv4 mapped, 0 otherwise. + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is IPv4 mapped, 0 otherwise. */ #define IN6_IS_ADDR_V4MAPPED(a) \ ((a)->__s6_addr.__s6_addr32[0] == 0 && \ @@ -231,8 +231,8 @@ This macro tests whether an IPv6 address (struct in6_addr *) is an IPv4 compatibility address. - \param a The address to test (struct in6_addr *) - \return Nonzero if the address is IPv4 compat, 0 otherwise. + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is IPv4 compat, 0 otherwise. */ #define IN6_IS_ADDR_V4COMPAT(a) \ ((a)->__s6_addr.__s6_addr32[0] == 0 && \ @@ -241,6 +241,104 @@ (a)->__s6_addr.__s6_addr32[3] != 0 && \ (a)->__s6_addr.__s6_addr8[15] != 1) +/** \brief Test if an IPv6 Address is a link-local address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a link-local + address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is link-local, 0 otherwise. +*/ +#define IN6_IS_ADDR_LINKLOCAL(a) \ + (((a)->__s6_addr.__s6_addr16[0] & 0xFFC0) == 0xFE80) + +/** \brief Test if an IPv6 Address is a site-local address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a site-local + address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is site-local, 0 otherwise. +*/ +#define IN6_IS_ADDR_SITELOCAL(a) \ + (((a)->__s6_addr.__s6_addr16[0] & 0xFFC0) == 0xFEC0) + +/** \brief Test if an IPv6 Address is a multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a multicast + address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is multicast, 0 otherwise. +*/ +#define IN6_IS_ADDR_MULTICAST(a) \ + ((a)->__s6_addr.__s6_addr8[0] == 0xFF) + +/** \brief Test if an IPv6 Address is a node-local multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a node-local + multicast address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a node-local multicast + address, 0 otherwise. +*/ +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x01) + +/** \brief Test if an IPv6 Address is a link-local multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a link-local + multicast address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a link-local multicast + address, 0 otherwise. +*/ +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x02) + +/** \brief Test if an IPv6 Address is a site-local multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a site-local + multicast address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a site-local multicast + address, 0 otherwise. +*/ +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x05) + +/** \brief Test if an IPv6 Address is an organization-local multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is an + organization-local multicast address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is an organization-local + multicast address, 0 otherwise. +*/ +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x08) + +/** \brief Test if an IPv6 Address is a global multicast address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a global + multicast address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a global multicast address, + 0 otherwise. +*/ +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + IN6_IS_ADDR_MULTICAST(a) && \ + (((a)->__s6_addr.__s6_addr8[1] & 0x0F) == 0x0E) + __END_DECLS #endif /* __NETINET_IN_H */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-16 01:53:26
|
Revision: 682 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=682&view=rev Author: ljsebald Date: 2010-10-16 01:53:20 +0000 (Sat, 16 Oct 2010) Log Message: ----------- - Fix a major bug in net_udp. - Remove some old stuff from init.c. Modified Paths: -------------- kos/kernel/arch/dreamcast/kernel/init.c kos/kernel/net/net_udp.c Modified: kos/kernel/arch/dreamcast/kernel/init.c =================================================================== --- kos/kernel/arch/dreamcast/kernel/init.c 2010-10-15 03:46:00 UTC (rev 681) +++ kos/kernel/arch/dreamcast/kernel/init.c 2010-10-16 01:53:20 UTC (rev 682) @@ -116,11 +116,7 @@ irq_enable(); /* Turn on IRQs */ maple_wait_scan(); /* Wait for the maple scan to complete */ } - /* if (!(__kos_init_flags & INIT_NO_DCLOAD) && *DCLOADMAGICADDR == DCLOADMAGICVALUE && - (__kos_init_flags & INIT_NET)) - { - old = dbgio_set_printk(dbgio_write_str); - } */ + if (__kos_init_flags & INIT_NET) { /* Check if the dcload-ip console is up, and if so, disable it, otherwise we'll crash when we attempt to bring up the BBA */ @@ -138,15 +134,7 @@ } } } - /* if (!(__kos_init_flags & INIT_NO_DCLOAD) && *DCLOADMAGICADDR == DCLOADMAGICVALUE && - (__kos_init_flags & INIT_NET)) - { - // dbgio_set_printk(old); - fs_dclnative_init(); - dbglog(DBG_INFO, "dc-load-ip native support enabled\n"); - } */ - return 0; } Modified: kos/kernel/net/net_udp.c =================================================================== --- kos/kernel/net/net_udp.c 2010-10-15 03:46:00 UTC (rev 681) +++ kos/kernel/net/net_udp.c 2010-10-16 01:53:20 UTC (rev 682) @@ -329,8 +329,6 @@ goto err; } - realaddr = (struct sockaddr_in *) addr; - if(udpsock->local_addr.sin_port == 0) { uint16 port = 1024, tmp = 0; struct udp_sock *iter; @@ -600,6 +598,11 @@ else if(net != NULL) { ps->src_addr = htonl(net_ipv4_address(net->ip_addr)); } + else { + errno = ENETDOWN; + ++udp_stats.pkt_send_failed; + return -1; + } } else { ps->src_addr = src_ip; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-15 03:46:06
|
Revision: 681 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=681&view=rev Author: ljsebald Date: 2010-10-15 03:46:00 +0000 (Fri, 15 Oct 2010) Log Message: ----------- - Change the IPv4 checksum function a little bit, so that we'll be able to calculate checksums with pseudo-headers a bit easier. - Update documentation in <arpa/inet.h> to reflect the fact that IPv6 does work with inet_ntop() and inet_pton(). - Fix a typo in a comment in <kos/fs_socket.h>. Modified Paths: -------------- kos/include/arpa/inet.h kos/include/kos/fs_socket.h kos/kernel/net/net_icmp.c kos/kernel/net/net_ipv4.c kos/kernel/net/net_ipv4.h kos/kernel/net/net_ipv4_frag.c kos/kernel/net/net_udp.c Modified: kos/include/arpa/inet.h =================================================================== --- kos/include/arpa/inet.h 2010-10-13 15:57:20 UTC (rev 680) +++ kos/include/arpa/inet.h 2010-10-15 03:46:00 UTC (rev 681) @@ -90,17 +90,18 @@ actually standard (in POSIX 2008), and operates very similarly. The only differences between this function and inet_aton are that this function does not support hexadecimal or octal representations and that this function has - the ability to support IPv6 (although currently since KOS only supports - IPv4, the function does not actually parse IPv6 addresses). This is the - function that you should actually use to convert addresses from strings to - binary in new code, rather than inet_addr or inet_aton. + the ability to support IPv6. This is the function that you should actually + use to convert addresses from strings to binary in new code, rather than + inet_addr or inet_aton. \param af The address family that src is an address in. The - only supported value currently is AF_INET (IPv4). + only supported values are AF_INET and AF_INET6. \param src A string representation of the address. \param dst Storage for the result. For AF_INET, this must be at least 32-bits in size (the function treats it as a - struct in_addr). + struct in_addr). For AF_INET6, this must be at least + 128-bits in size (the function treats it as a struct + in6_addr). \retval -1 af is unsupported. \retval 0 An invalid address was given. \retval 1 Upon successful conversion. @@ -115,14 +116,14 @@ This function does the exact oposite of the inet_pton function, converting a binary form of an address to a string. This function, unlike inet_ntoa, is reentrant, and is the function that you should generally use if you need to - convert a binary representation of an IP address to a string. Note that this - function, like all of KOS' network system, does not support IPv6. + convert a binary representation of an IP address to a string. \param af The address family that src is in. The only - supported value currently is AF_INET (IPv4). + supported values are AF_INET and AF_INET6. \param src A binary representation of an IP address. \param dst Storage for the resulting string. This string should - be at least 16-bytes long for IPv4. + be at least 16-bytes long for IPv4, and 46 bytes for + IPv6. \param size The length of dst. \retval NULL Upon failed conversion. \retval dst Upon successful conversion. Modified: kos/include/kos/fs_socket.h =================================================================== --- kos/include/kos/fs_socket.h 2010-10-13 15:57:20 UTC (rev 680) +++ kos/include/kos/fs_socket.h 2010-10-15 03:46:00 UTC (rev 681) @@ -227,7 +227,7 @@ \retval -1 On error (set errno appropriately) \retval 0 No outstanding data and the peer has disconnected cleanly - \retval n T he number of bytes received (may be less than len) + \retval n The number of bytes received (may be less than len) */ ssize_t (*recvfrom)(net_socket_t *s, void *buffer, size_t len, int flags, struct sockaddr *addr, socklen_t *alen); Modified: kos/kernel/net/net_icmp.c =================================================================== --- kos/kernel/net/net_icmp.c 2010-10-13 15:57:20 UTC (rev 680) +++ kos/kernel/net/net_icmp.c 2010-10-15 03:46:00 UTC (rev 681) @@ -107,7 +107,7 @@ /* Recompute the ICMP header checksum */ icmp->checksum = 0; icmp->checksum = net_ipv4_checksum((uint8 *)icmp, ntohs(ip->length) - - 4 * (ip->version_ihl & 0x0f)); + 4 * (ip->version_ihl & 0x0f), 0); /* Set the destination to the original source, and substitute in our IP for the src (done this way so that pings that are broadcasted get an @@ -123,7 +123,7 @@ icmp = (icmp_hdr_t*)d; /* Check the ICMP checksum */ - i = net_ipv4_checksum(d, s); + i = net_ipv4_checksum(d, s, 0); if (i) { dbglog(DBG_KDEBUG, "net_icmp: icmp with invalid checksum\n"); @@ -177,7 +177,7 @@ memcpy(databuf + sizeof(icmp_hdr_t), data, size); /* Compute the ICMP Checksum */ - icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + size); + icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + size, 0); /* If we're sending to the loopback, set that as our source too. */ if(ipaddr[0] == 127) { @@ -220,7 +220,7 @@ memcpy(databuf + sizeof(icmp_hdr_t), orig_msg, sz); /* Compute the ICMP Checksum */ - icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz); + icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz, 0); /* Send the packet away */ return net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + sz, 0, 255, 1, @@ -245,7 +245,7 @@ memcpy(databuf + sizeof(icmp_hdr_t), orig_msg, sz); /* Compute the ICMP Checksum */ - icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz); + icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz, 0); /* Send the packet away */ return net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + sz, 0, 255, 1, Modified: kos/kernel/net/net_ipv4.c =================================================================== --- kos/kernel/net/net_ipv4.c 2010-10-13 15:57:20 UTC (rev 680) +++ kos/kernel/net/net_ipv4.c 2010-10-15 03:46:00 UTC (rev 681) @@ -21,8 +21,8 @@ static net_ipv4_stats_t ipv4_stats = { 0 }; /* Perform an IP-style checksum on a block of data */ -uint16 net_ipv4_checksum(const uint8 *data, int bytes) { - uint32 sum = 0; +uint16 net_ipv4_checksum(const uint8 *data, int bytes, uint16 start) { + uint32 sum = start; int i; /* Make sure we don't do any unaligned memory accesses */ @@ -179,7 +179,7 @@ hdr.src = src; hdr.dest = dst; - hdr.checksum = net_ipv4_checksum((uint8 *)&hdr, sizeof(ip_hdr_t)); + hdr.checksum = net_ipv4_checksum((uint8 *)&hdr, sizeof(ip_hdr_t), 0); return net_ipv4_frag_send(net, &hdr, data, size); } @@ -208,7 +208,7 @@ /* Check ip header checksum */ i = ip->checksum; ip->checksum = 0; - ip->checksum = net_ipv4_checksum((uint8 *)ip, hdrlen); + ip->checksum = net_ipv4_checksum((uint8 *)ip, hdrlen, 0); if(i != ip->checksum) { /* The checksums don't match, bail */ Modified: kos/kernel/net/net_ipv4.h =================================================================== --- kos/kernel/net/net_ipv4.h 2010-10-13 15:57:20 UTC (rev 680) +++ kos/kernel/net/net_ipv4.h 2010-10-15 03:46:00 UTC (rev 681) @@ -43,7 +43,7 @@ } packed ip_pseudo_hdr_t; #undef packed -uint16 net_ipv4_checksum(const uint8 *data, int bytes); +uint16 net_ipv4_checksum(const uint8 *data, int bytes, uint16 start); int net_ipv4_send_packet(netif_t *net, ip_hdr_t *hdr, const uint8 *data, int size); int net_ipv4_send(netif_t *net, const uint8 *data, int size, int id, int ttl, Modified: kos/kernel/net/net_ipv4_frag.c =================================================================== --- kos/kernel/net/net_ipv4_frag.c 2010-10-13 15:57:20 UTC (rev 680) +++ kos/kernel/net/net_ipv4_frag.c 2010-10-15 03:46:00 UTC (rev 681) @@ -218,7 +218,7 @@ /* Recompute the checksum. */ newhdr.checksum = 0; - newhdr.checksum = net_ipv4_checksum((uint8 *)&newhdr, sizeof(ip_hdr_t)); + newhdr.checksum = net_ipv4_checksum((uint8 *)&newhdr, sizeof(ip_hdr_t), 0); if(net_ipv4_send_packet(net, &newhdr, data, ds)) { return -1; @@ -230,7 +230,7 @@ hdr->length = htons(ihl + size - ds); hdr->flags_frag_offs = htons((flags & 0xE000) | ((flags & 0x1FFF) + nfb)); hdr->checksum = 0; - hdr->checksum = net_ipv4_checksum((uint8 *)hdr, sizeof(ip_hdr_t)); + hdr->checksum = net_ipv4_checksum((uint8 *)hdr, sizeof(ip_hdr_t), 0); return net_ipv4_frag_send(net, hdr, data + ds, size - ds); } Modified: kos/kernel/net/net_udp.c =================================================================== --- kos/kernel/net/net_udp.c 2010-10-13 15:57:20 UTC (rev 680) +++ kos/kernel/net/net_udp.c 2010-10-15 03:46:00 UTC (rev 681) @@ -522,7 +522,7 @@ #if 1 checksum = ps->checksum; ps->checksum = 0; - ps->checksum = net_ipv4_checksum(buf, size + 12); + ps->checksum = net_ipv4_checksum(buf, size + 12, 0); if(checksum != ps->checksum) { /* The checksums don't match, bail out */ @@ -530,7 +530,7 @@ return -1; } #else - if(net_ipv4_checksum(buf, size + 12)) { + if(net_ipv4_checksum(buf, size + 12, 0)) { /* The checksum was wrong, bail out */ ++udp_stats.pkt_recv_bad_chksum; return -1; @@ -616,7 +616,7 @@ ps->dst_port = dst_port; ps->hdrlength = ps->length; ps->checksum = 0; - ps->checksum = net_ipv4_checksum(buf, size + 12); + ps->checksum = net_ipv4_checksum(buf, size + 12, 0); retry_send: /* Pass everything off to the network layer to do the rest. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-13 15:57:26
|
Revision: 680 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=680&view=rev Author: ljsebald Date: 2010-10-13 15:57:20 +0000 (Wed, 13 Oct 2010) Log Message: ----------- Add a few more IPv6-related macros to <netinet/in.h>. Add IPv6 support to inet_ntop. Modified Paths: -------------- kos/include/netinet/in.h kos/kernel/libc/koslib/inet_ntop.c Modified: kos/include/netinet/in.h =================================================================== --- kos/include/netinet/in.h 2010-10-13 04:18:38 UTC (rev 679) +++ kos/include/netinet/in.h 2010-10-13 15:57:20 UTC (rev 680) @@ -10,9 +10,8 @@ This file contains the standard definitions (as directed by the POSIX 2008 standard) for internet-related functionality in the AF_INET address family. - This does not include anything related to AF_INET6 (as IPv6 is not currently - implemented in KOS), and is not guaranteed to have everything that one might - have in a fully-standard compliant implementation of the POSIX standard. + This does is not guaranteed to have everything that one might have in a + fully-standard compliant implementation of the POSIX standard. \author Lawrence Sebald */ @@ -213,6 +212,35 @@ (a)->__s6_addr.__s6_addr8[14] == 0 && \ (a)->__s6_addr.__s6_addr8[15] == 1) +/** \brief Test if an IPv6 Address is an IPv4 mapped address. + + This macro tests whether an IPv6 address (struct in6_addr *) is an IPv4 + mapped address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is IPv4 mapped, 0 otherwise. +*/ +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((a)->__s6_addr.__s6_addr32[0] == 0 && \ + (a)->__s6_addr.__s6_addr32[1] == 0 && \ + (a)->__s6_addr.__s6_addr16[4] == 0 && \ + (a)->__s6_addr.__s6_addr16[5] == 0xFFFF) + +/** \brief Test if an IPv6 Address is an IPv4 compatibility address. + + This macro tests whether an IPv6 address (struct in6_addr *) is an IPv4 + compatibility address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is IPv4 compat, 0 otherwise. +*/ +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((a)->__s6_addr.__s6_addr32[0] == 0 && \ + (a)->__s6_addr.__s6_addr32[1] == 0 && \ + (a)->__s6_addr.__s6_addr32[2] == 0 && \ + (a)->__s6_addr.__s6_addr32[3] != 0 && \ + (a)->__s6_addr.__s6_addr8[15] != 1) + __END_DECLS #endif /* __NETINET_IN_H */ Modified: kos/kernel/libc/koslib/inet_ntop.c =================================================================== --- kos/kernel/libc/koslib/inet_ntop.c 2010-10-13 04:18:38 UTC (rev 679) +++ kos/kernel/libc/koslib/inet_ntop.c 2010-10-13 15:57:20 UTC (rev 680) @@ -1,29 +1,24 @@ /* KallistiOS ##version## inet_ntop.c - Copyright (C) 2007 Lawrence Sebald + Copyright (C) 2007, 2010 Lawrence Sebald */ #include <arpa/inet.h> #include <errno.h> -const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { +static const char *inet_ntop4(const void *src, char *dst, socklen_t size) { char tmp[3]; int i, part; char *ch = tmp; char *ch2 = dst; struct in_addr *addr = (struct in_addr *)src; - if(af != AF_INET) { - errno = EAFNOSUPPORT; - return NULL; - } - /* Parse each 8 bits individually. */ for(i = 0; i < 4; ++i) { /* Treat the 32-bit address value as if it were an array of 8-bit - values. This works, regardless of the endianness of the host system + values. This works regardless of the endianness of the host system because the specs require the address passed in here to be in network byte order (big endian). */ part = ((uint8 *) &addr->s_addr)[i]; @@ -42,6 +37,7 @@ } if(!size) { + dst[0] = 0; errno = ENOSPC; return NULL; } @@ -56,3 +52,166 @@ return dst; } + +static const char *inet_ntop6(const void *src, char *dst, socklen_t size) { + struct in6_addr *addr = (struct in6_addr *)src; + int tmp[8] = { 0 }; + int runstart = -1, maxzero = 0, dcs = -1, i; + char tmpstr[4]; + char *ch = tmpstr, *ch2 = dst; + int part; + + /* Handle the special cases of IPv4 Mapped and Compatibility addresses */ + if(IN6_IS_ADDR_V4MAPPED(addr)) { + if(size > 7) { + dst[0] = dst[1] = dst[6] = ':'; + dst[2] = dst[3] = dst[4] = dst[5] = 'f'; + + /* Parse the IPv4 address at the end */ + if(!inet_ntop4(&addr->__s6_addr.__s6_addr32[3], dst + 7, size - 7)) + goto err; + + return dst; + } + else { + goto err; + } + } + else if(IN6_IS_ADDR_V4COMPAT(addr)) { + if(size > 2) { + dst[0] = dst[1] = ':'; + + /* Parse the IPv4 address at the end */ + if(!inet_ntop4(&addr->__s6_addr.__s6_addr32[3], dst + 2, size - 2)) + goto err; + + return dst; + } + else { + goto err; + } + } + + /* Figure out if we have any use for double colons in the address or not */ + for(i = 0; i < 8; ++i) { + if(addr->__s6_addr.__s6_addr16[i] == 0) { + if(runstart != -1) { + ++tmp[runstart]; + } + else { + runstart = i; + tmp[i] = 1; + } + + if(tmp[runstart] > maxzero) { + maxzero = tmp[runstart]; + dcs = runstart; + } + } + else { + runstart = -1; + } + } + + /* We should now know where the double colons will be, and how many zeroes + they will replace, the rest is pretty easy. */ + i = 0; + + if(dcs == 0) { + if(size > 2) { + *ch2++ = ':'; + *ch2++ = ':'; + size -= 2; + i = maxzero; + } + else { + goto err; + } + } + + while(i < 8) { + if(i == dcs) { + if(size > 1) { + *ch2++ = ':'; + --size; + i += maxzero; + } + else { + goto err; + } + } + else { + part = ntohs(addr->__s6_addr.__s6_addr16[i]); + + do { + *ch = (char)(part & 0x0f) + '0'; + part >>= 4; + + /* Deal with digits greater than 9 */ + if(*ch > '9') { + *ch = *ch - ':' + 'a'; + } + + ch++; + } while(part); + + /* tmp now contains the inverse of the number that is in the given + 16 bits. Reverse it for the final result, rewinding ch to the + beginning of tmpstr in the process. */ + while(ch != tmpstr && size) { + *ch2++ = *--ch; + --size; + } + + if(size < 1) { + goto err; + } + + *ch2++ = ':'; + --size; + ++i; + } + } + + /* Change the last : to a NUL terminator, unless the last set was where we + had a run of zeroes replaced by a :: */ + if(dcs + maxzero != 8) { + *(ch2 - 1) = 0; + } + else if(size > 0) { + *ch2 = 0; + } + else { + goto err; + } + + return dst; + +err: + /* In the event of an error, clear whatever we may have done */ + for(i = 0; i < size; ++i) { + dst[i] = 0; + } + + errno = ENOSPC; + return NULL; +} + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { + if(size < 1) { + errno = ENOSPC; + return NULL; + } + + switch(af) { + case AF_INET: + return inet_ntop4(src, dst, size); + + case AF_INET6: + return inet_ntop6(src, dst, size); + + default: + errno = EAFNOSUPPORT; + return NULL; + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-13 04:18:44
|
Revision: 679 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=679&view=rev Author: ljsebald Date: 2010-10-13 04:18:38 +0000 (Wed, 13 Oct 2010) Log Message: ----------- Fix double colons with IPv4 address embedded inside an IPv6 address in inet_pton6. Modified Paths: -------------- kos/kernel/libc/koslib/inet_pton.c Modified: kos/kernel/libc/koslib/inet_pton.c =================================================================== --- kos/kernel/libc/koslib/inet_pton.c 2010-10-13 04:04:05 UTC (rev 678) +++ kos/kernel/libc/koslib/inet_pton.c 2010-10-13 04:18:38 UTC (rev 679) @@ -113,6 +113,11 @@ return 0; } + /* Adjust the after double colon count for embedded IPv4 addresses. */ + if(ip4start && dc) { + afterdc += 2; + } + ++afterdc; /* Reset these, since we need them reset below to start the parsing. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-10-13 04:04:12
|
Revision: 678 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=678&view=rev Author: ljsebald Date: 2010-10-13 04:04:05 +0000 (Wed, 13 Oct 2010) Log Message: ----------- Adding IPv6 address parsing support to inet_pton. Modified Paths: -------------- kos/include/netinet/in.h kos/include/sys/socket.h kos/kernel/libc/koslib/inet_pton.c kos/kernel/net/Makefile Added Paths: ----------- kos/kernel/net/net_ipv6.c Modified: kos/include/netinet/in.h =================================================================== --- kos/include/netinet/in.h 2010-08-21 18:59:33 UTC (rev 677) +++ kos/include/netinet/in.h 2010-10-13 04:04:05 UTC (rev 678) @@ -45,13 +45,26 @@ in_addr_t s_addr; }; +/** \brief Structure used to store an IPv6 address. + \headerfile netinet/in.h +*/ +struct in6_addr { + union { + uint8_t __s6_addr8[16]; + uint16_t __s6_addr16[8]; + uint32_t __s6_addr32[4]; + uint64_t __s6_addr64[2]; + } __s6_addr; +#define s6_addr __s6_addr.__s6_addr8 +}; + /* Bring in <arpa/inet.h> to make ntohl/ntohs/htonl/htons visible, as per IEEE Std 1003.1-2008 (the standard specifically states that <netinet/in.h> may make all symbols from <arpa/inet.h> visible. The <arpa/inet.h> header actually needs the stuff above, so that's why we include it here. */ #include <arpa/inet.h> -/** \brief Structure used to store an address for a socket. +/** \brief Structure used to store an IPv4 address for a socket. This structure is the standard way to set up addresses for sockets in the AF_INET address family. Generally you will not send one of these directly @@ -75,6 +88,31 @@ unsigned char sin_zero[8]; }; +/** \brief Structure used to store an IPv6 address for a socket. + + This structure is the standard way to set up addresses for sockets in the + AF_INET6 address family. Generally you will not send one of these directly + to a function, but rather will cast it to a struct sockaddr. + + \headerfile netinet/in.h + */ +struct sockaddr_in6 { + /** \brief Family for the socket. Must be AF_INET6. */ + sa_family_t sin6_family; + + /** \brief Port for the socket. Must be in network byte order. */ + in_port_t sin6_port; + + /** \brief Traffic class and flow information. */ + uint32_t sin6_flowinfo; + + /** \brief Address for the socket. Must be in network byte order. */ + struct in6_addr sin6_addr; + + /** \brief Set of interfaces for a scope. */ + uint32_t sin6_scope_id; +}; + /** \brief Local IPv4 host address. This address can be used by many things if you prefer to not specify the @@ -96,10 +134,41 @@ */ #define INADDR_NONE 0xFFFFFFFF +/** \brief Initialize an IPv6 local host address. + + This macro can be used to initialize a struct in6_addr to any lcoal address. + It functions similarly to INADDR_ANY for IPv4. +*/ +#define IN6ADDR_ANY_INIT {{{ 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0 }}} + +/** \brief Initialize an IPv6 loopback address. + + This macro can be used to initialize a struct in6_addr to the loopback + address. +*/ +#define IN6ADDR_LOOPBACK_INIT {{{ 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 1 }}} + +/** \brief IPv6 local host address. + + This constant variable contains the IPv6 local host address. +*/ +extern const struct in6_addr in6addr_any; + +/** \brief IPv6 loopback address. + + This constant variable contains the IPv6 loopback address. +*/ +extern const struct in6_addr in6addr_loopback; + /** \brief Length of a string form of a maximal IPv4 address. */ #define INET_ADDRSTRLEN 16 -/** \brief Internet Protocol. */ +/** \brief Length of a string form of a maximal IPv6 address. */ +#define INET6_ADDRSTRLEN 46 + +/** \brief Internet Protocol Version 4. */ #define IPPROTO_IP 0 /** \brief Internet Control Message Protocol. */ @@ -111,6 +180,39 @@ /** \brief User Datagram Protocol. */ #define IPPROTO_UDP 17 +/** \brief Internet Protocol Version 6. */ +#define IPPROTO_IPV6 41 + +/** \brief Test if an IPv6 Address is unspecified. + + This macro tests whether an IPv6 address (struct in6_addr *) is an + unspecified address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is unspecified, 0 otherwise. +*/ +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + ((a)->__s6_addr.__s6_addr32[0] == 0 && \ + (a)->__s6_addr.__s6_addr32[1] == 0 && \ + (a)->__s6_addr.__s6_addr32[2] == 0 && \ + (a)->__s6_addr.__s6_addr32[3] == 0) + +/** \brief Test if an IPv6 Address is a loopback address. + + This macro tests whether an IPv6 address (struct in6_addr *) is a + loopback address. + + \param a The address to test (struct in6_addr *) + \return Nonzero if the address is a loopback, 0 otherwise. +*/ +#define IN6_IS_ADDR_LOOPBACK(a) \ + ((a)->__s6_addr.__s6_addr32[0] == 0 && \ + (a)->__s6_addr.__s6_addr32[1] == 0 && \ + (a)->__s6_addr.__s6_addr32[2] == 0 && \ + (a)->__s6_addr.__s6_addr16[6] == 0 && \ + (a)->__s6_addr.__s6_addr8[14] == 0 && \ + (a)->__s6_addr.__s6_addr8[15] == 1) + __END_DECLS #endif /* __NETINET_IN_H */ Modified: kos/include/sys/socket.h =================================================================== --- kos/include/sys/socket.h 2010-08-21 18:59:33 UTC (rev 677) +++ kos/include/sys/socket.h 2010-10-13 04:04:05 UTC (rev 678) @@ -51,11 +51,20 @@ #define SOCK_DGRAM 1 /** \brief Internet domain sockets for use with IPv4 addresses. */ -#define AF_INET 1 +#define AF_INET 1 -/** \brief Protocol family for Internet domain sockets. */ -#define PF_INET AF_INET +/** \brief Internet domain sockets for use with IPv6 addresses. + Note, these are NOT supported just yet. +*/ +#define AF_INET6 2 + +/** \brief Protocol family for Internet domain sockets (IPv4). */ +#define PF_INET AF_INET + +/** \brief Protocol family for Internet domain sockets (IPv6). */ +#define PF_INET6 AF_INET6 + /** \brief Disable furhter receive operations. */ #define SHUT_RD 0x00000001 Modified: kos/kernel/libc/koslib/inet_pton.c =================================================================== --- kos/kernel/libc/koslib/inet_pton.c 2010-08-21 18:59:33 UTC (rev 677) +++ kos/kernel/libc/koslib/inet_pton.c 2010-10-13 04:04:05 UTC (rev 678) @@ -1,23 +1,18 @@ /* KallistiOS ##version## inet_pton.c - Copyright (C) 2007 Lawrence Sebald + Copyright (C) 2007, 2010 Lawrence Sebald */ #include <arpa/inet.h> #include <errno.h> -int inet_pton(int af, const char *src, void *dst) { +static int inet_pton4(const char *src, void *dst) { int parts[4] = { 0 }; int count = 0; struct in_addr *addr = (struct in_addr *)dst; - if(af != AF_INET) { - errno = EAFNOSUPPORT; - return -1; - } - for(; *src && count < 4; ++src) { if(*src == '.') { ++count; @@ -49,3 +44,149 @@ return 1; } + +static int inet_pton6(const char *src, void *dst) { + uint32_t parts[8] = { 0 }; + struct in6_addr *addr = (struct in6_addr *)dst; + int wc = 0, dc = 0, afterdc = 0; + int pos = 0, i; + const char *tmp = src, *ip4start = NULL; + struct in_addr ip4addr; + + /* This loop simply checks the address for validity. Its split up in two + parts (check and parse) like this for simplicity and clarity. */ + for(; *tmp; ++tmp) { + if(*tmp == ':') { + if(wc && dc) { + /* If we have a double colon again after a double colon (or we + have 3 colons in a row), its an error. Bail out. */ + return 0; + } + else if(ip4start) { + /* If we have any dots, we can't have any colons after! */ + return 0; + } + else if(wc) { + dc = 1; + } + else if(dc) { + ++afterdc; + } + + wc = 1; + } + else if(*tmp == '.') { + /* If this is the first part of the IPv4, figure out where it starts + in the string */ + if(!ip4start) { + for(ip4start = tmp; ip4start > src; --ip4start) { + if(*ip4start == ':') { + ++ip4start; + break; + } + } + } + } + else if((*tmp >= '0' && *tmp <= '9') || (*tmp >= 'A' && *tmp <= 'F') || + (*tmp >= 'a' && *tmp <= 'f')) { + wc = 0; + } + else { + /* Invalid character encountered, bail out */ + return 0; + } + } + + /* Make sure if we have a colon at the end, its a double colon, not a single + colon. Double colon is fine, single colon is invalid. */ + if(*(tmp - 1) == ':' && *(tmp - 2) != ':') { + return 0; + } + + /* Same deal at the beginning of the string. */ + if(*src == ':' && *(src + 1) != ':') { + return 0; + } + + /* If we have any dots, attempt to parse out the IPv4 address. */ + if(ip4start && inet_pton4(ip4start, &ip4addr) != 1) { + return 0; + } + + ++afterdc; + + /* Reset these, since we need them reset below to start the parsing. */ + wc = dc = 0; + + for(; *src && (!ip4start || src < ip4start); ++src) { + if(*src == ':') { + if(wc) { + /* We have a double colon, advance as far as we need to. */ + if(pos + afterdc >= 8) { + /* The double colon is invalid wherever it is. */ + return 0; + } + + dc = 1; + pos = 8 - afterdc; + } + else { + /* Advance to the next 16-bit set */ + wc = 1; + ++pos; + } + } + else if(*src >= '0' && *src <= '9') { + parts[pos] <<= 4; + parts[pos] |= *src - '0'; + wc = 0; + } + else if(*src >= 'a' && *src <= 'f') { + parts[pos] <<= 4; + parts[pos] |= *src - 'a' + 0x0A; + wc = 0; + } + else if(*src >= 'A' && *src <= 'F') { + parts[pos] <<= 4; + parts[pos] |= *src - 'A' + 0x0A; + wc = 0; + } + + if(parts[pos] > 0xFFFF) { + /* We've overflowed, bail */ + return 0; + } + } + + if((!ip4start && pos != 7) || (ip4start && pos != 5)) { + /* We didn't fill in the whole address... */ + return 0; + } + + /* If we've gotten here, everything's good, so fill in the real address. */ + for(i = 0; i < 8; ++i) { + addr->__s6_addr.__s6_addr16[i] = htons((uint16_t)parts[i]); + } + + /* If we have an IPv4 address embedded, put it in too. */ + if(ip4start) { + addr->__s6_addr.__s6_addr32[3] = ip4addr.s_addr; + } + + /* And, we're done. */ + return 1; +} + +int inet_pton(int af, const char *src, void *dst) { + switch(af) { + case AF_INET: + return inet_pton4(src, dst); + + case AF_INET6: + return inet_pton6(src, dst); + + default: + errno = EAFNOSUPPORT; + return -1; + } +} Modified: kos/kernel/net/Makefile =================================================================== --- kos/kernel/net/Makefile 2010-08-21 18:59:33 UTC (rev 677) +++ kos/kernel/net/Makefile 2010-10-13 04:04:05 UTC (rev 678) @@ -5,7 +5,7 @@ # OBJS = net_core.o net_arp.o net_input.o net_icmp.o net_ipv4.o net_udp.o -OBJS += net_dhcp.o net_ipv4_frag.o net_thd.o +OBJS += net_dhcp.o net_ipv4_frag.o net_thd.o net_ipv6.o SUBDIRS = include $(KOS_BASE)/Makefile.prefab Added: kos/kernel/net/net_ipv6.c =================================================================== --- kos/kernel/net/net_ipv6.c (rev 0) +++ kos/kernel/net/net_ipv6.c 2010-10-13 04:04:05 UTC (rev 678) @@ -0,0 +1,13 @@ +/* KallistiOS ##version## + + kernel/net/net_ipv6.c + Copyright (C) 2010 Lawrence Sebald + +*/ + +#include <netinet/in.h> + +/* Note, this doesn't actually implement IPv6 just yet. Its just a skeleton to + deal with a few little things */ +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fa...@us...> - 2010-08-21 18:59:39
|
Revision: 677 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=677&view=rev Author: fackue Date: 2010-08-21 18:59:33 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Adding BlueCrab's init fini Newlib patch. Modified Paths: -------------- kos/utils/dc-chain/patches/newlib-1.18.0-kos.diff Modified: kos/utils/dc-chain/patches/newlib-1.18.0-kos.diff =================================================================== --- kos/utils/dc-chain/patches/newlib-1.18.0-kos.diff 2010-07-27 01:10:16 UTC (rev 676) +++ kos/utils/dc-chain/patches/newlib-1.18.0-kos.diff 2010-08-21 18:59:33 UTC (rev 677) @@ -9,6 +9,33 @@ ;; sparc*) machine_dir=sparc +diff -ruN newlib-1.18.0/newlib/libc/include/assert.h newlib-1.18.0-kos/newlib/libc/include/assert.h +--- newlib-1.18.0/newlib/libc/include/assert.h 2008-07-17 16:56:51.000000000 -0400 ++++ newlib-1.18.0-kos/newlib/libc/include/assert.h 2010-07-29 15:33:25.000000000 -0400 +@@ -13,8 +13,8 @@ + #ifdef NDEBUG /* required by ANSI standard */ + # define assert(__e) ((void)0) + #else +-# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \ +- __ASSERT_FUNC, #__e)) ++# define assert(__e) ((__e) ? (void)0 : __assert (__FILE__, __LINE__, #__e, \ ++ (char *)0, __ASSERT_FUNC)) + + # ifndef __ASSERT_FUNC + /* Use g++'s demangled names in C++. */ +@@ -36,10 +36,8 @@ + # endif /* !__ASSERT_FUNC */ + #endif /* !NDEBUG */ + +-void _EXFUN(__assert, (const char *, int, const char *) +- _ATTRIBUTE ((__noreturn__))); +-void _EXFUN(__assert_func, (const char *, int, const char *, const char *) +- _ATTRIBUTE ((__noreturn__))); ++void _EXFUN(__assert, (const char *, int, const char *, const char *, ++ const char *) _ATTRIBUTE ((__noreturn__))); + + #ifdef __cplusplus + } diff -ruN newlib-1.18.0/newlib/libc/include/sys/types.h newlib-1.18.0-kos/newlib/libc/include/sys/types.h --- newlib-1.18.0/newlib/libc/include/sys/types.h 2009-09-28 12:42:21.000000000 -0400 +++ newlib-1.18.0-kos/newlib/libc/include/sys/types.h 2010-06-13 19:05:19.000000000 -0400 @@ -78,6 +105,22 @@ #else #if defined (__CYGWIN__) #include <cygwin/types.h> +diff -ruN newlib-1.18.0/newlib/libc/stdlib/assert.c newlib-1.18.0-kos/newlib/libc/stdlib/assert.c +--- newlib-1.18.0/newlib/libc/stdlib/assert.c 2009-10-08 12:44:10.000000000 -0400 ++++ newlib-1.18.0-kos/newlib/libc/stdlib/assert.c 2010-07-29 14:12:29.000000000 -0400 +@@ -65,6 +65,7 @@ + } + #endif /* HAVE_ASSERT_FUNC */ + ++#if 0 + void + _DEFUN (__assert, (file, line, failedexpr), + const char *file _AND +@@ -74,3 +75,4 @@ + __assert_func (file, line, NULL, failedexpr); + /* NOTREACHED */ + } ++#endif diff -ruN newlib-1.18.0/newlib/libc/sys/sh/ftruncate.c newlib-1.18.0-kos/newlib/libc/sys/sh/ftruncate.c --- newlib-1.18.0/newlib/libc/sys/sh/ftruncate.c 2003-07-10 11:31:30.000000000 -0400 +++ newlib-1.18.0-kos/newlib/libc/sys/sh/ftruncate.c 2010-06-13 18:59:43.000000000 -0400 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-27 01:10:22
|
Revision: 676 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=676&view=rev Author: ljsebald Date: 2010-07-27 01:10:16 +0000 (Tue, 27 Jul 2010) Log Message: ----------- Add support for sending ICMPv4 Destination Unreachable and Time Exceeded packets. Also, change how ICMPv4 Echo packets are handled slightly. Modified Paths: -------------- kos/examples/dreamcast/network/ping/ping.c kos/include/kos/net.h kos/kernel/net/net_icmp.c kos/kernel/net/net_icmp.h kos/kernel/net/net_ipv4.c Modified: kos/examples/dreamcast/network/ping/ping.c =================================================================== --- kos/examples/dreamcast/network/ping/ping.c 2010-07-27 01:08:15 UTC (rev 675) +++ kos/examples/dreamcast/network/ping/ping.c 2010-07-27 01:10:16 UTC (rev 676) @@ -37,7 +37,7 @@ /* Send out 10 pings, waiting 250ms between attempts. */ for(i = 0; i < 10; ++i) { - net_icmp_send_echo(net_default_dev, addr, data, DATA_SIZE); + net_icmp_send_echo(net_default_dev, addr, 0, i, data, DATA_SIZE); thd_sleep(250); } Modified: kos/include/kos/net.h =================================================================== --- kos/include/kos/net.h 2010-07-27 01:08:15 UTC (rev 675) +++ kos/include/kos/net.h 2010-07-27 01:10:16 UTC (rev 676) @@ -2,7 +2,7 @@ include/kos/net.h Copyright (C) 2002 Dan Potter - Copyright (C) 2005, 2006, 2007, 2008, 2009 Lawrence Sebald + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Lawrence Sebald */ @@ -201,9 +201,22 @@ extern net_echo_cb net_icmp_echo_cb; /* Send an ICMP Echo packet to the specified IP. */ -int net_icmp_send_echo(netif_t *net, const uint8 ipaddr[4], const uint8 *data, - int size); +int net_icmp_send_echo(netif_t *net, const uint8 ipaddr[4], uint16 ident, + uint16 seq, const uint8 *data, int size); +/* Valid values for the code in the net_icmp_send_dest_unreach() function. */ +#define ICMP_PROTOCOL_UNREACHABLE 2 +#define ICMP_PORT_UNREACHABLE 3 + +/* Send an ICMP Destination Unreachable packet in reply to the given message */ +int net_icmp_send_dest_unreach(netif_t *net, uint8 code, const uint8 *msg); + +/* Valid values for the code in the net_icmp_send_time_exceeded() function. */ +#define ICMP_REASSEMBLY_TIME_EXCEEDED 1 + +/* Send an ICMP Time Exceeded packet in reply to the given message */ +int net_icmp_send_time_exceeded(netif_t *net, uint8 code, const uint8 *msg); + /***** net_ipv4.c *********************************************************/ /* IPv4 statistics structure. This structure holds some basic statistics about Modified: kos/kernel/net/net_icmp.c =================================================================== --- kos/kernel/net/net_icmp.c 2010-07-27 01:08:15 UTC (rev 675) +++ kos/kernel/net/net_icmp.c 2010-07-27 01:10:16 UTC (rev 676) @@ -3,7 +3,7 @@ kernel/net/net_icmp.c Copyright (C) 2002 Dan Potter - Copyright (C) 2005, 2006, 2007, 2009 Lawrence Sebald + Copyright (C) 2005, 2006, 2007, 2009, 2010 Lawrence Sebald */ @@ -22,18 +22,33 @@ This file implements RFC 792, the Internet Control Message Protocol. Currently implemented message types are: 0 - Echo Reply + 3 - Destination Unreachable 8 - Echo + 11 - Time Exceeded Message types that are not implemented yet (if ever): - 3 - Destination Unreachable 4 - Source Quench 5 - Redirect - 11 - Time Exceeded + 6 - Alternate Host Address + 9 - Router Advertisement + 10 - Router Solicitation 12 - Parameter Problem 14 - Timestamp Reply 13 - Timestamp 15 - Information Request 16 - Information Reply + 17 - Address Mask Request + 18 - Address Mask Reply + 30 - Traceroute + 31 - Datagram Conversion Error + 32 - Mobile Host Redirect + 33 - Where-Are-You + 34 - Here-I-Am + 35 - Mobile Registration Request + 36 - Mobile Registration Reply + 37 - Domain Name Request + 38 - Domain Name Reply + Any other numbers not listed in the earlier list... */ struct ping_pkt { @@ -48,7 +63,6 @@ LIST_HEAD(ping_pkt_list, ping_pkt); static struct ping_pkt_list pings = LIST_HEAD_INITIALIZER(0); -static uint16 icmp_echo_seq = 1; static void icmp_default_echo_cb(const uint8 *ip, uint16 seq, uint64 delta_us, uint8 ttl, const uint8* data, int data_sz) { @@ -88,7 +102,7 @@ static void net_icmp_input_8(netif_t *src, ip_hdr_t *ip, icmp_hdr_t *icmp, const uint8 *d, int s) { /* Set type to echo reply */ - icmp->type = 0; + icmp->type = ICMP_MESSAGE_ECHO_REPLY; /* Recompute the ICMP header checksum */ icmp->checksum = 0; @@ -98,7 +112,7 @@ /* Set the destination to the original source, and substitute in our IP for the src (done this way so that pings that are broadcasted get an appropriate reply), and send it away. */ - net_ipv4_send(src, d, s, ip->packet_id, ip->ttl, 1, ip->dest, ip->src); + net_ipv4_send(src, d, s, ip->packet_id, 255, 1, ip->dest, ip->src); } int net_icmp_input(netif_t *src, ip_hdr_t *ip, const uint8 *d, int s) { @@ -117,19 +131,24 @@ } switch(icmp->type) { - case 0: /* Echo reply */ + case ICMP_MESSAGE_ECHO_REPLY: net_icmp_input_0(src, ip, icmp, d, s); break; - case 3: /* Destination unreachable */ - dbglog(DBG_KDEBUG, "net_icmp: Destination unreachable," + case ICMP_MESSAGE_DEST_UNREACHABLE: + dbglog(DBG_WARNING, "net_icmp: Destination unreachable," " code %d\n", icmp->code); break; - case 8: /* Echo */ + case ICMP_MESSAGE_ECHO: net_icmp_input_8(src, ip, icmp, d, s); break; + case ICMP_MESSAGE_TIME_EXCEEDED: + dbglog(DBG_WARNING, "net_icmp: Time exceeded, code %d\n", + icmp->code); + break; + default: dbglog(DBG_KDEBUG, "net_icmp: unknown icmp type: %d\n", icmp->type); @@ -139,25 +158,22 @@ } /* Send an ICMP Echo (PING) packet to the specified device */ -int net_icmp_send_echo(netif_t *net, const uint8 ipaddr[4], const uint8 *data, - int size) { +int net_icmp_send_echo(netif_t *net, const uint8 ipaddr[4], uint16 ident, + uint16 seq, const uint8 *data, int size) { icmp_hdr_t *icmp; struct ping_pkt *newping; int r = -1; uint8 databuf[sizeof(icmp_hdr_t) + size]; - uint16 seq = icmp_echo_seq++; uint32 src; icmp = (icmp_hdr_t *)databuf; /* Fill in the ICMP Header */ - icmp->type = 8; /* Echo */ + icmp->type = ICMP_MESSAGE_ECHO; /* Echo */ icmp->code = 0; icmp->checksum = 0; - icmp->misc[0] = (uint8) 'D'; - icmp->misc[1] = (uint8) 'C'; - icmp->misc[2] = (uint8) (seq >> 8); - icmp->misc[3] = (uint8) (seq & 0xFF); + icmp->misc.m16[0] = htons(ident); + icmp->misc.m16[1] = htons(seq); memcpy(databuf + sizeof(icmp_hdr_t), data, size); /* Compute the ICMP Checksum */ @@ -180,9 +196,58 @@ LIST_INSERT_HEAD(&pings, newping, pkt_list); newping->usec = timer_us_gettime64(); - r = net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + size, seq, 64, 1, - htonl(src), - htonl(net_ipv4_address(ipaddr))); + r = net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + size, seq, 255, 1, + htonl(src), htonl(net_ipv4_address(ipaddr))); return r; } + +/* Send an ICMP Destination Unreachable packet in reply to the given message */ +int net_icmp_send_dest_unreach(netif_t *net, uint8 code, const uint8 *msg) { + icmp_hdr_t *icmp; + const ip_hdr_t *orig_msg = (ip_hdr_t *)msg; + int hdrsz = (orig_msg->version_ihl & 0x0F) << 2; + int sz = ((hdrsz + 8) > orig_msg->length) ? orig_msg->length : (hdrsz + 8); + uint8 databuf[sizeof(icmp_hdr_t) + sz]; + + icmp = (icmp_hdr_t *)databuf; + + /* Fill in the ICMP Header */ + icmp->type = ICMP_MESSAGE_DEST_UNREACHABLE; + icmp->code = code; + icmp->checksum = 0; + icmp->misc.m32 = 0; + memcpy(databuf + sizeof(icmp_hdr_t), orig_msg, sz); + + /* Compute the ICMP Checksum */ + icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz); + + /* Send the packet away */ + return net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + sz, 0, 255, 1, + orig_msg->dest, orig_msg->src); +} + +/* Send an ICMP Time Exceeded packet in reply to the given message */ +int net_icmp_send_time_exceeded(netif_t *net, uint8 code, const uint8 *msg) { + icmp_hdr_t *icmp; + const ip_hdr_t *orig_msg = (ip_hdr_t *)msg; + int hdrsz = (orig_msg->version_ihl & 0x0F) << 2; + int sz = ((hdrsz + 8) > orig_msg->length) ? orig_msg->length : (hdrsz + 8); + uint8 databuf[sizeof(icmp_hdr_t) + sz]; + + icmp = (icmp_hdr_t *)databuf; + + /* Fill in the ICMP Header */ + icmp->type = ICMP_MESSAGE_TIME_EXCEEDED; + icmp->code = code; + icmp->checksum = 0; + icmp->misc.m32 = 0; + memcpy(databuf + sizeof(icmp_hdr_t), orig_msg, sz); + + /* Compute the ICMP Checksum */ + icmp->checksum = net_ipv4_checksum(databuf, sizeof(icmp_hdr_t) + sz); + + /* Send the packet away */ + return net_ipv4_send(net, databuf, sizeof(icmp_hdr_t) + sz, 0, 255, 1, + orig_msg->dest, orig_msg->src); +} Modified: kos/kernel/net/net_icmp.h =================================================================== --- kos/kernel/net/net_icmp.h 2010-07-27 01:08:15 UTC (rev 675) +++ kos/kernel/net/net_icmp.h 2010-07-27 01:10:16 UTC (rev 676) @@ -2,7 +2,7 @@ kernel/net/net_icmp.h Copyright (C) 2002 Dan Potter - Copyright (C) 2005, 2007 Lawrence Sebald + Copyright (C) 2005, 2007, 2010 Lawrence Sebald */ @@ -17,13 +17,22 @@ #define packed __attribute__((packed)) typedef struct { - uint8 type; - uint8 code; - uint16 checksum; - uint8 misc[4]; + uint8 type; + uint8 code; + uint16 checksum; + union { + uint8 m8[4]; + uint16 m16[2]; + uint32 m32; + } misc; } packed icmp_hdr_t; #undef packed +#define ICMP_MESSAGE_ECHO_REPLY 0 +#define ICMP_MESSAGE_DEST_UNREACHABLE 3 +#define ICMP_MESSAGE_ECHO 8 +#define ICMP_MESSAGE_TIME_EXCEEDED 11 + int net_icmp_input(netif_t *src, ip_hdr_t *ih, const uint8 *data, int size); __END_DECLS Modified: kos/kernel/net/net_ipv4.c =================================================================== --- kos/kernel/net/net_ipv4.c 2010-07-27 01:08:15 UTC (rev 675) +++ kos/kernel/net/net_ipv4.c 2010-07-27 01:10:16 UTC (rev 676) @@ -2,7 +2,7 @@ kernel/net/net_ipv4.c - Copyright (C) 2005, 2006, 2007, 2008, 2009 Lawrence Sebald + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Lawrence Sebald Portions adapted from KOS' old net_icmp.c file: Copyright (c) 2002 Dan Potter @@ -236,8 +236,11 @@ return net_udp_input(src, ip, data, ntohs(ip->length) - hdrlen); } - /* There's no handler for this packet type, bail out */ + /* There's no handler for this packet type, send an ICMP Destination + Unreachable, and log the unknown protocol. */ ++ipv4_stats.pkt_recv_bad_proto; + net_icmp_send_dest_unreach(src, ICMP_PROTOCOL_UNREACHABLE, (uint8 *)ip); + return -1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-27 01:08:22
|
Revision: 675 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=675&view=rev Author: ljsebald Date: 2010-07-27 01:08:15 +0000 (Tue, 27 Jul 2010) Log Message: ----------- More Doxygen comments... Modified Paths: -------------- kos/doc/Doxyfile kos/include/kos/cond.h kos/include/kos/fs_pty.h kos/include/kos/library.h kos/include/kos/mutex.h kos/include/kos/nmmgr.h kos/include/kos/sem.h kos/include/sys/_types.h kos/kernel/arch/dreamcast/include/dc/biosfont.h kos/kernel/arch/dreamcast/include/dc/ubc.h Modified: kos/doc/Doxyfile =================================================================== --- kos/doc/Doxyfile 2010-07-20 20:05:07 UTC (rev 674) +++ kos/doc/Doxyfile 2010-07-27 01:08:15 UTC (rev 675) @@ -307,7 +307,7 @@ # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. @@ -1003,7 +1003,7 @@ # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup @@ -1050,7 +1050,7 @@ # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. -PAPER_TYPE = a4wide +PAPER_TYPE = letter # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. @@ -1298,7 +1298,9 @@ PREDEFINED = _arch_$(KOS_ARCH)=1 \ __BEGIN_DECLS= \ - __END_DECLS= + __END_DECLS= \ + __extension__= \ + __packed__= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. Modified: kos/include/kos/cond.h =================================================================== --- kos/include/kos/cond.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/cond.h 2010-07-27 01:08:15 UTC (rev 675) @@ -56,10 +56,10 @@ \headerfile kos/cond.h */ typedef struct condvar { - /* \cond */ + /** \cond */ /* List entry for the global list of condvars */ LIST_ENTRY(condvar) g_list; - /* \endcond */ + /** \endcond */ } condvar_t; /* \cond */ @@ -71,10 +71,10 @@ This function allocates and initializes a new condition variable for use. \return The created condvar on success. NULL is returned on - failure, and errno is set as appropriate. + failure and errno is set as appropriate. \par Error Conditions: - \em ENOMEM - Out of memory + \em ENOMEM - out of memory */ condvar_t *cond_create(); @@ -93,10 +93,10 @@ this function has no timeout, and will sleep forever if the condition is not signalled. - \param cv The condition to wait on. - \param m The associated mutex. - \retval 0 On success. - \retval -1 On error, sets errno as appropriate. + \param cv The condition to wait on + \param m The associated mutex + \retval 0 On success + \retval -1 On error, sets errno as appropriate \par Error Conditions: \em EPERM - Called inside an interrupt \n @@ -112,14 +112,14 @@ the lock more than once (since this function only unlocks it once). This was added specifically because it was required for GCC's C++0x threading code. - \param cv The condition to wait on. - \param l The associated lock. - \retval 0 On success. - \retval -1 On error, sets errno as appropriate. + \param cv The condition to wait on + \param l The associated lock + \retval 0 On success + \retval -1 On error, sets errno as appropriate \par Error Conditions: \em EPERM - Called inside an interrupt \n - \em EINTR - Was interrupted. + \em EINTR - Was interrupted \author Lawrence Sebald */ @@ -133,11 +133,11 @@ If a timeout of 0 is given, the call is equivalent to cond_wait() (there is no timeout). - \param cv The condition to wait on. - \param m The associated mutex. - \param timeout The number of milliseconds before timeout. - \retval 0 On success. - \retval -1 On error, sets errno as appropriate. + \param cv The condition to wait on + \param m The associated mutex + \param timeout The number of milliseconds before timeout + \retval 0 On success + \retval -1 On error, sets errno as appropriate \par Error Conditions: \em EPERM - Called inside an interrupt \n @@ -155,11 +155,11 @@ no timeout). The rant about cond_wait_recursive() being evil applies here as well. - \param cv The condition to wait on. + \param cv The condition to wait on \param l The associated recursive lock. - \param timeout The number of milliseconds before timeout. - \retval 0 On success. - \retval -1 On error, sets errno as appropriate. + \param timeout The number of milliseconds before timeout + \retval 0 On success + \retval -1 On error, sets errno as appropriate \par Error Conditions: \em EPERM - Called inside an interrupt \n @@ -176,7 +176,7 @@ The calling thread should be holding the associated mutex or recursive lock before calling this to guarantee sane behavior. - \param cv The condition to signal. + \param cv The condition to signal */ void cond_signal(condvar_t *cv); @@ -186,15 +186,15 @@ The calling thread should be holding the associated mutex or recursive lock before calling this to guarantee sane behavior. - \param cv The condition to signal. + \param cv The condition to signal */ void cond_broadcast(condvar_t *cv); /* Init / shutdown */ -/* \cond */ +/** \cond */ int cond_init(); void cond_shutdown(); -/* \endcond */ +/** \endcond */ __END_DECLS Modified: kos/include/kos/fs_pty.h =================================================================== --- kos/include/kos/fs_pty.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/fs_pty.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,6 +5,20 @@ */ +/** \file kos/fs_pty.h + \brief Pseudo-terminal virtual file system. + + This file system implements a pseudo-terminal like concept (similar to + /dev/pty in Linux). A call to fs_pty_create() will crate two file entries in + the VFS, /pty/maXX and /pty/slXX (XX being some hexadecimal number). From + there, anybody can open up either end and send data to the other side. Think + of it as a simple message passing interface. + + This file system mounts on /pty. + + \author Dan Potter +*/ + #ifndef __KOS_FS_PTY_H #define __KOS_FS_PTY_H @@ -15,13 +29,32 @@ #include <kos/limits.h> #include <kos/fs.h> -/* Call this function to create a new pty. The name of the pty is written - into the user-provided buffer (if non-NULL) and two open file descriptors - pointing to the two ends of the pty are returned. */ +/** \brief Create a new pseudo-terminal. + + This function creates a new pseudo-terminal, opening up two files in the + /pty portion of the VFS. + + \param buffer Storage for the name of the PTY, apparently not + actually used (but potentially will be fixed at some + point). If it was implemented, the name of the PTY + would be here on successful return (if not NULL) + \param maxbuflen The length of buffer + \param master_out A pointer to store the file descriptor for the + master end in (must not be NULL) + \param slave_out A pointer to store the file descriptor for the slave + end in (must not be NULL) + \retval 0 On success + \retval -1 On error + + \par Error Conditions: + \em ENOMEM - out of memory +*/ int fs_pty_create(char * buffer, int maxbuflen, file_t * master_out, file_t * slave_out); +/** \cond */ int fs_pty_init(); int fs_pty_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/kos/library.h =================================================================== --- kos/include/kos/library.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/library.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,6 +5,23 @@ */ +/** \file kos/library.h + \brief Dynamically loadable library support. + + This file contains definitions for accessing loadable libraries at runtime. + Each library has a name and a version number that it can be referenced by. + One must be careful with these dynamic libraries as there is no private + storage per instance, and all memory space is shared. + + Libraries can both export and import symbols. Imported symbols may require + other libraries to be loaded earlier. Libraries are reference counted so + that they can be opened multiple times without actually loading them + multiple times, and so that a close will act as expected in situations like + this. + + \author Dan Potter +*/ + #ifndef __KOS_LIBRARY_H #define __KOS_LIBRARY_H @@ -15,107 +32,242 @@ #include <kos/elf.h> #include <kos/fs.h> +/** \cond */ /* Pre-define list/queue types */ struct klibrary; TAILQ_HEAD(klqueue, klibrary); LIST_HEAD(kllist, klibrary); +/** \endcond */ /* Thread IDs are ok for us */ -typedef tid_t libid_t; +typedef tid_t libid_t; /**< \brief Library ID type. */ -/* Structure describing one loaded library. Each lib basically consists of - a set of loaded program code and a set of standard exported entry points. */ +/** \brief Loaded library structure. + + This structure represents a single loaded library. Each library is + essentially a loaded binary of code and a set of exported entry points that + are standardized. + + Each loaded library should export at least the functions described in this + structure: + \li const char *lib_get_name() + \li uint32 %lib_get_version() + \li int lib_open(struct klibrary *lib) + \li int lib_close(struct klibrary *lib) + + You should not modify any members of this structure yourself (except if you + are implementing a library). + + \headerfile kos/library.h +*/ typedef struct klibrary { - /* Library list handle */ - LIST_ENTRY(klibrary) list; + /** \brief Library list handle. - /* Kernel library id */ - libid_t libid; + Contrary to what doxygen might think, this is not a function. + */ + LIST_ENTRY(klibrary) list; - /* Flags */ - uint32 flags; + /** \brief Library ID (assigned at runtime). */ + libid_t libid; - /* ELF program image for this library */ - elf_prog_t image; + /** \brief Library flags. */ + uint32 flags; - /* The library's reference count. If it is opened more than once, this - will go to >1 values. The library is actually shut down and removed - if this reaches zero. */ - int refcnt; + /** \brief ELF image for this library. - /* Standard library entry points. Every loaded library must provide - at least these things. */ + This can be used to look up additional entry points in the library. + */ + elf_prog_t image; - /* Return a pointer to a string containing the library's symbolic - name. Must work before calling lib_open. */ - const char * (*lib_get_name)(); + /** \brief Library reference count. - /* Return an integer containing the library's version ID. Must work - before calling lib_open. */ - uint32 (*lib_get_version)(); + This value is incremented every time the library is opened, and + decremented each time it is closed. Once the library's reference count + hits 0, a close will actually destroy the library. + */ + int refcnt; - /* "Open" the library (i.e., init and/or increase ref count). Return - >= 0 value here to signal success. If failure is signaled on the - first lib_open, it is assumed we can remove this library from memory. */ - int (*lib_open)(struct klibrary * lib); + /* Standard library entry points. Every loaded library must provide + at least these things. */ - /* "Close" the library (i.e., dec ref count and/or shut down). Return - >= 0 on success or < 0 on failure. */ - int (*lib_close)(struct klibrary * lib); + /** \brief Retrieve the library's symbolic name. + + This function must be implemented by all loadable libraries to fetch the + library's symbolic name. This function must work before calling + lib_open() on the library. + + \return The library's symbolic name + */ + const char * (*lib_get_name)(); + + /** \brief Retrieve the library's version. + + This function must be implemented by all loadble libraries to fetch the + library's version number. This function must work before calling + lib_open() on the library. + + \return The library's version number + */ + uint32 (*lib_get_version)(); + + /** \brief Open a library. + + This function must be implemented by all loadable libraries to + initialize the library on load. If the library is already opened, this + may only involve increasing the reference count. + + \param lib The library structure + \return Values >= 0 indicate success, < 0 indicates failure. + A failure on the first lib_open is indicative that + the library should be removed from memory. + */ + int (*lib_open)(struct klibrary * lib); + + /** \brief Close an opened library. + + This function must be implemented by all loadable libraries to close and + deinitialize a library. If the library's reference count is > 1 when + this function is called, this may involve simply decrementing the + reference count. + + \param lib The library structure + \return Values >= 0 indicate success, < 0 indicates failure + */ + int (*lib_close)(struct klibrary * lib); } klibrary_t; /* Library flag values */ -#define LIBRARY_DEFAULTS 0 /* Defaults: no flags */ +#define LIBRARY_DEFAULTS 0 /**< \brief Defaults: no flags */ +/** \cond */ /* Library list; note: do not manipulate directly */ extern struct kllist library_list; +/** \endcond */ -/* Given a library ID, locates the lib structure */ +/** \brief Look up a library by ID. + + This function looks up a library by its library ID. + + \param libid The library ID to look up + \return The specified library, or NULL if not found +*/ klibrary_t *library_by_libid(libid_t libid); -/* New library shell function. When you want to load a new library, this - function will handle that for you. This will generally only be used by - the library code internally. */ +/** \brief Create a new library shell. + + This function creates a new library, adding it to the list of libraries. You + generally should not call this function directly, unless you have some good + reason to do so. + + \param flags Flags to create the library with. + \return The newly created library, or NULL on error +*/ klibrary_t *library_create(int flags); -/* Given a library handle, this function removes the library from the library - list. Any remaining resources assigned to this library will be freed. This - will generally only be used by the library code internally. */ +/** \brief Destroy a library. + + This function will take a loaded library and destroy it, unloading it + completely. Generally, you should not call this function, but rather use + library_close() to make sure that you're not closing something that is still + in use. + + \param lib The library to close + \retval 0 Upon successfully destroying the library +*/ int library_destroy(klibrary_t *lib); -/* Try to open a library by symbolic name. If the library open fails, then - attempt to load the library from the given filename. If this fails, then - return NULL for error. On success, return a handle to the library; - lib_open will already have been called. */ +/** \brief Try to open a library by name. + + This function attempts to open a library by its name. If it cannot be found + by name, this function will attempt to load the library from the specified + filename. + + \param name The symbolic name of the library + \param fn The filename to load the library from + \return A handle to the library, or NULL on error with errno + set as appropriate + + \par Error Conditions: + \em EINVAL - the library was found or loaded, but invalid \n + \em ENOMEM - out of memory \n + \em ENOENT - library not found and no filename given +*/ klibrary_t * library_open(const char * name, const char * fn); -/* Look up a library by name without trying to load or open it. This is - useful if you want to open a library in one place and not have to keep - track of the handle to close it later. */ +/** \brief Look up a library by name. + + This function looks up a library by its symbolic name without trying to + actually load or open it. This is useful if you want to open a library but + not keep around a handle to it (which isn't necessarily encouraged). + + \param name The name of the library to search for + \return The library, if found. NULL if not found, errno set + as appropriate. + + \par Error Conditions: + \em ENOENT - the library was not found +*/ klibrary_t * library_lookup(const char * name); -/* Close a previously opened library. If this fails, return < 0 for error. If - it succeeds, return > 0; lib_close will already have been called, and the - library may have been destroyed as well (do NOT try to use it again). */ +/** \brief Close a previously opened library. + + This function will close the specified library. This may involve simply + decrementing its reference count, however, it may also involve actually + closing and freeing the library. Thus, don't try to use the library after + calling this without reopening it first. + + \param lib The library to close + \retval 0 On success + \retval -1 On error, errno may be set to an appropriate code + + \par Error Conditions: + \em EINVAL - the library is not valid +*/ int library_close(klibrary_t * lib); -/* Retrieve library's libid (runtime ID) */ +/** \brief Retrieve the specified library's runtime-assigned ID. + \param lib The library to examine + \return The library's ID, or -1 on error + + \par Error Conditions: + \em EINVAL - the library is not valid +*/ libid_t library_get_libid(klibrary_t * lib); -/* Retrieve library's reference count */ +/** \brief Retrieve the specified library's reference count. + \param lib The library to examine + \return The library's reference count, or -1 on error + + \par Error Conditions: + \em EINVAL - the library is not valid +*/ int library_get_refcnt(klibrary_t * lib); -/* Retrieve library's name */ +/** \brief Retrieve the specified library's name. + \param lib The library to examine + \return The library's symbolic name, or NULL on error + + \par Error Conditions: + \em EINVAL - the library is not valid +*/ const char * library_get_name(klibrary_t * lib); -/* Retrieve library's version */ +/** \brief Retrieve the specified library's version. + \param lib The library to examine + \return The library's version number, or 0 on error + + \par Error Conditions + \em EINVAL - the library is not valid +*/ uint32 library_get_version(klibrary_t * lib); +/** \cond */ /* Init */ int library_init(); /* Shutdown */ void library_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/kos/mutex.h =================================================================== --- kos/include/kos/mutex.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/mutex.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,6 +5,23 @@ */ +/** \file kos/mutex.h + \brief Mutual exclusion locks. + + This file defines mutual exclusion locks (or mutexes for short). The concept + of a mutex is one of the most common types of locks in a multi-threaded + environment. Mutexes do exactly what they sound like, they keep two (or + more) threads mutually exclusive from one another. A mutex is used around + a block of code to prevent two threads from interfereing with one another + when only one would be appropriate to be in the block at a time. + + KallistiOS simply implements its mutexes as a wrapper around semaphores with + an initial count of 1. + + \author Dan Potter + \see kos/sem.h +*/ + #ifndef __KOS_MUTEX_H #define __KOS_MUTEX_H @@ -14,39 +31,116 @@ /* These are just wrappers around semaphores */ #include <kos/sem.h> +/** \brief Mutual exclusion lock type. + + KOS mutexes are just wrappers around semaphores. + + \headerfile kos/mutex.h +*/ typedef semaphore_t mutex_t; -/* Create a mutex. Sets errno to ENOMEM on failure. */ +/** \brief Allocate a new mutex. + + This function allocates and initializes a new mutex for use. + + \return The created mutex on success. NULL is returned on + failure and errno is set as appropriate. + + \par Error Conditions: + \em ENOMEM - out of memory +*/ mutex_t * mutex_create(); -/* Destroy a mutex */ +/** \brief Free a mutex. + + This function frees a mutex, releasing all memory associated with it. It is + your responsibility to make sure that all threads waiting on the mutex are + taken care of before destroying the mutex. +*/ void mutex_destroy(mutex_t * m); -/* Attempt to lock the mutex; if it's busy, then block. Returns 0 on - success, -1 on error. - EPERM - called inside interrupt - EINTR - wait was interrupted */ +/** \brief Lock a mutex. + + This function will lock a mutex, if it is not already locked by another + thread. If it is locked by another thread already, this function will block + until the mutex has been acquired for the calling thread. + + This does not protect against a thread obtaining the same mutex twice or any + other deadlock conditions. Also, this function is not safe to call inside an + interrupt. For mutex locks inside interrupts, use mutex_trylock(). + + \param m The mutex to acquire + \retval 0 On success + \retval -1 On error, sets errno as appropriate + + \par Error Conditions: + \em EPERM - called inside an interrupt \n + \em EINTR - was interrupted +*/ int mutex_lock(mutex_t * m); -/* Attempt to lock the mutex; if it's busy and it takes longer than the - timeout (milliseconds) then return an error. - EPERM - called inside interrupt - EINTR - wait was interrupted - EAGAIN - timed out */ +/** \brief Lock a mutex (with a timeout). + + This function will attempt to lock a mutex. If the lock can be acquired + immediately, the function will return immediately. If not, the function will + block for up to the specified number of milliseconds to wait for the lock. + If the lock cannot be acquired in this timeframe, this function will return + an error. + + Much like mutex_lock(), this function does not protect against deadlocks + and is not safe to call in an interrupt. + + \param m The mutex to acquire + \param timeout The number of milliseconds to wait for the lock + \retval 0 On success + \retval -1 On error, errno will be set as appropriate + + \par Error Conditions: + \em EPERM - called inside an interrupt \n + \em EINTR - was interrupted \n + \em EAGAIN - timed out while blocking +*/ int mutex_lock_timed(mutex_t * m, int timeout); -/* Check to see whether the mutex is available; note that this is not - a threadsafe way to figure out if it _will_ be locked by the time you - get to locking it. */ +/** \brief Check if a mutex is locked. + + This function will check whether or not a mutex is currently locked. This is + not a thread-safe way to determine if the mutex will be locked by the time + you get around to doing it. If you wish to attempt to lock a mutex without + blocking, look at mutex_trylock(), not this. + + \param m The mutex to check + \retval 0 If the mutex is not currently locked + \retval 1 If the mutex is currently locked +*/ int mutex_is_locked(mutex_t * m); -/* Attempt to lock the mutex. If the mutex would block, then return an - error instead of actually blocking. Note that this function, unlike - the other waits, DOES work inside an interrupt. - EAGAIN - would block */ +/** \brief Attempt to lock a mutex. + + This function will attempt to acquire the mutex for the calling thread, + returning immediately whether or not it could be acquired. If the mutex + cannot be acquired, an error will be returned. + + This function is safe to call inside an interrupt. + + \param m The mutex to attempt to acquire + \retval 0 On successfully acquiring the mutex + \retval -1 If the mutex cannot be acquired without blocking + + \par Error Conditions: + \em EAGAIN - the mutex is already locked (mutex_lock() would block) +*/ int mutex_trylock(mutex_t * m); -/* Unlock the mutex */ +/** \brief Unlock a mutex. + + This function will unlock a mutex, allowing other threads to acquire it. + This function does not check if the thread that is calling it holds the + mutex. It is your responsibility to make sure you only unlock mutexes that + you have locked. + + \param m The mutex to unlock +*/ void mutex_unlock(mutex_t * m); __END_DECLS Modified: kos/include/kos/nmmgr.h =================================================================== --- kos/include/kos/nmmgr.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/nmmgr.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,6 +5,16 @@ */ +/** \file kos/nmmgr.h + \brief Name manager. + + This file contains the definitions of KOS' name manager. A "name" is a + generic identifier for some kind of module. These modules may include + services provided by the kernel (such as VFS handlers). + + \author Dan Potter +*/ + #ifndef __KOS_NMMGR_H #define __KOS_NMMGR_H @@ -17,14 +27,28 @@ /* Pre-define list types */ struct nmmgr_handler; + +/** \brief Name handler list type. + + Contrary to what doxygen may think, this is not a function. +*/ typedef LIST_HEAD(nmmgr_list, nmmgr_handler) nmmgr_list_t; -/* List entry initializer for static structs */ +/** \brief List entry initializer for static structs. + + If you are creating nmmgr handlers, this is what you should initialize the + list_ent member with. +*/ #define NMMGR_LIST_INIT { NULL } -/* Handler interface; all name handlers' must structs must begin with this - prefix. If the handler conforms to some particular interface, then the - struct must more specifically be of that type. */ +/** \brief Name handler interface. + + Every name handler must begin its information structures with this header. + If the handler conforms to some well-defined interface (such as a VFS), then + the struct must more specifically be of that type. + + \headerfile kos/nmmgr.h +*/ typedef struct nmmgr_handler { char pathname[MAX_FN_LEN]; /* Path name */ int pid; /* Process table ID for handler (0 == static) */ @@ -40,30 +64,72 @@ mostly-compatible but newer/older revisions of the implementing code. */ /* Flag bits */ -#define NMMGR_FLAGS_NEEDSFREE 0x00000001 /* We need to free() this struct on remove */ +/** \brief This structure must be freed when removed. */ +#define NMMGR_FLAGS_NEEDSFREE 0x00000001 -/* Name handler types. All "system" types are defined below 0x10000. */ +/** \defgroup nmmgr_types Name handler types + + This is the set of all defined types of name manager handlers. All system + types are defined below NMMGR_SYS_MAX. + + @{ +*/ +/** \brief Unknown nmmgr type. */ #define NMMGR_TYPE_UNKNOWN 0x0000 /* ? */ +/** \brief A mounted filesystem. */ #define NMMGR_TYPE_VFS 0x0010 /* Mounted file system */ +/** \brief A block device. */ #define NMMGR_TYPE_BLOCKDEV 0x0020 /* Block device */ +/** \brief A singleton service (e.g., /dev/irq) */ #define NMMGR_TYPE_SINGLETON 0x0030 /* Singleton service (e.g., /dev/irq) */ +/** \brief A symbol table. */ #define NMMGR_TYPE_SYMTAB 0x0040 /* Symbol table */ +/** \brief Everything this and above is a user type. */ #define NMMGR_SYS_MAX 0x10000 /* Here and above are user types */ +/** @} */ -/* Given a pathname, return the name handler corresponding to it - (or NULL if there is none). */ +/** \brief Retrieve a name handler by name. + + This function will retrieve a name handler by its pathname. + + \param name The handler to look up + \return The handler, or NULL on failure. +*/ nmmgr_handler_t * nmmgr_lookup(const char *name); -/* Get the head element of our name list. This is for READ-ONLY PURPOSES ONLY. */ +/** \brief Get the head element of the name list. + + DO NOT MODIFY THE VALUE RETURNED BY THIS FUNCTION! In fact, don't ever call + this function. + + \return The head of the name handler list +*/ nmmgr_list_t * nmmgr_get_list(); -/* Add/Remove a name handler module */ +/** \brief Add a name handler. + + This function adds a new name handler to the list in the kernel. + + \param hnd The handler to add + \retval 0 On success +*/ int nmmgr_handler_add(nmmgr_handler_t *hnd); + +/** \brief Remove a name handler. + + This function removes a name handler from the list in the kernel. + + \param hnd The handler to remove + \retval 0 On success + \retval -1 If the handler wasn't found +*/ int nmmgr_handler_remove(nmmgr_handler_t *hnd); +/** \cond */ /* Name manager init */ int nmmgr_init(); void nmmgr_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/kos/sem.h =================================================================== --- kos/include/kos/sem.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/kos/sem.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,6 +5,22 @@ */ +/** \file kos/sem.h + \brief Semaphores. + + This file defines semaphores. A semaphore is a synchronization primitive + that allows a spcified number of threads to be in its critical section at a + single point of time. Another way to think of it is that you have a + predetermined number of resources available, and the semaphore maintains the + resources. + + A special case of semaphores are mutual exclusion locks. Mutual exclusion + locks are simply semaphores that have a count of 1 initially. + + \author Dan Potter + \see kos/mutex.h +*/ + #ifndef __KOS_SEM_H #define __KOS_SEM_H @@ -15,54 +31,141 @@ #include <sys/queue.h> #include <kos/thread.h> -/* Semaphore structure definition */ +/** \brief Semaphore type. + + This structure defines a semaphore. There are no public members of this + structure for you to actually do anything with in your code, so don't try. + + \headerfile kos/sem.h +*/ typedef struct semaphore { + /** \cond */ /* List entry for the global list of semaphores */ LIST_ENTRY(semaphore) g_list; /* Basic semaphore info */ int count; /* The semaphore count */ + /** \endcond */ } semaphore_t; +/** \cond */ LIST_HEAD(semlist, semaphore); +/** \endcond */ -/* Allocate a new semaphore. Sets errno to ENOMEM on failure. */ +/** \brief Allocate a new semaphore. + + This function allocates and initializes a new semaphore for use. + + \param value The initial count of the semaphore (the number of + threads to allow in the critical section at a time) + + \return The created semaphore on success. NULL is returned + on failure and errno is set as appropriate. + + \par Error Conditions: + \em ENOMEM - out of memory +*/ semaphore_t *sem_create(int value); -/* Free a semaphore */ +/** \brief Free a semaphore. + + This function frees a semaphore, releasing all memory associated with it. It + is your responsibility to make sure that all threads waiting on the + semaphore are taken care of before destroying the semaphore. +*/ void sem_destroy(semaphore_t *sem); -/* Wait on a semaphore. Returns -1 on error: - EPERM - called inside interrupt - EINTR - wait was interrupted */ +/** \brief Wait on a semaphore. + + This function will decrement the semaphore's count and return, if resources + are available. Otherwise, the function will block until the resources become + available. + + This function does not protect you against doing things that will cause a + deadlock. This function is not safe to call in an interrupt. See + sem_trywait() for a safe function to call in an interrupt. + + \param sem The semaphore to wait on + \retval 0 On success + \retval -1 On error, sets errno as appropriate + + \par Error Conditions: + \em EPERM - called inside an interrupt \n + \em EINTR - was interrupted +*/ int sem_wait(semaphore_t *sem); -/* Wait on a semaphore, with timeout (in milliseconds); returns -1 - on failure, otherwise 0. - EPERM - called inside interrupt - EINTR - wait was interrupted - EAGAIN - timed out */ +/** \brief Wait on a semaphore (with a timeout). + + This function will decrement the semaphore's count and return, if resources + are available. Otherwise, the function will block until the resources become + available or the timeout expires. + + This function does not protect you against doing things that will cause a + deadlock. This function is not safe to call in an interrupt. See + sem_trywait() for a safe function to call in an interrupt. + + \param sem The semaphore to wait on + \param timeout The maximum number of milliseconds to block + \retval 0 On success + \retval -1 On error, sets errno as appropriate + + \par Error Conditions: + \em EPERM - called inside an interrupt \n + \em EINTR - was interrupted \n + \em EAGAIN - timed out while blocking + */ int sem_wait_timed(semaphore_t *sem, int timeout); /* Attempt to wait on a semaphore. If the semaphore would block, then return an error instead of actually blocking. Note that this function, unlike the other waits, DOES work inside an interrupt. EAGAIN - would block */ +/** \brief "Wait" on a semaphore without blocking. + + This function will decrement the semaphore's count and return, if resources + are available. Otherwise, it will return an error. + + This function does not protect you against doing things that will cause a + deadlock. This function, unlike the other waiting functions is safe to call + inside an interrupt. + + \param sem The semaphore to "wait" on + \retval 0 On success + \retval -1 On error, sets errno as appropriate + + \par Error Conditions: + \em EAGAIN - resources are not available (sem_wait() would block) +*/ int sem_trywait(semaphore_t *sem); -/* Signal a semaphore */ +/** \brief Signal a semaphore. + + This function will release resources associated with a semaphore, signalling + a waiting thread to continue on, if any are waiting. It is your + responsibility to make sure you only release resources you have. + + \param sem The semaphore to signal +*/ void sem_signal(semaphore_t *sem); -/* Return the semaphore count */ +/** \brief Retrieve the number of available resources. + + This function will retrieve the count of available resources for a + semaphore. This is not a thread-safe way to make sure resources will be + available when you get around to waiting, so don't use it as such. + + \param sem The semaphore to check + \return The count of the semaphore (the number of resources + currently available) +*/ int sem_count(semaphore_t *sem); -/* Called by the periodic thread interrupt to look for timed out - sem_wait_timed calls */ -void sem_check_timeouts(); - +/** \cond */ /* Init / shutdown */ int sem_init(); void sem_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/sys/_types.h =================================================================== --- kos/include/sys/_types.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/include/sys/_types.h 2010-07-27 01:08:15 UTC (rev 675) @@ -1,3 +1,11 @@ +/** \file sys/_types.h + \brief Internal typedefs. + + This file contains internal typedefs required by libc. You probably + shouldn't use any of these in your code. Most of these are copied from + newlib's %sys/_types.h. +*/ + #ifndef _SYS__TYPES_H #define _SYS__TYPES_H @@ -5,45 +13,55 @@ // This part copied from newlib's sys/_types.h. #ifndef __off_t_defined +/** \brief File offset type. */ typedef long _off_t; #endif #ifndef __dev_t_defined +/** \brief Device ID type. */ typedef short __dev_t; #endif #ifndef __uid_t_defined +/** \brief User ID type. */ typedef unsigned short __uid_t; #endif #ifndef __gid_t_defined +/** \brief Group ID type. */ typedef unsigned short __gid_t; #endif #ifndef __off64_t_defined +/** \brief 64-bit file offset type. */ __extension__ typedef long long _off64_t; #endif #ifndef __fpos_t_defined +/** \brief File position type. */ typedef long _fpos_t; #endif #ifdef __LARGE64_FILES #ifndef __fpos64_t_defined +/** \brief 64-bit file position type. */ typedef _off64_t _fpos64_t; #endif #endif #if defined(__INT_MAX__) && __INT_MAX__ == 2147483647 +/** \brief Signed size type. */ typedef int _ssize_t; #else typedef long _ssize_t; #endif +/** \cond */ #define __need_wint_t #include <stddef.h> +/** \endcond */ #ifndef __mbstate_t_defined -/* Conversion state information. */ +/** \brief Conversion state information. */ typedef struct { int __count; @@ -56,16 +74,18 @@ #endif #ifndef __flock_t_defined +/** \brief File lock type. */ typedef __newlib_recursive_lock_t _flock_t; #endif #ifndef __iconv_t_defined -/* Iconv descriptor type */ +/** \brief Iconv descriptor type. */ typedef void *_iconv_t; #endif // This part inserted to fix newlib brokenness. +/** \brief Size of an fd_set. */ #define FD_SETSIZE 1024 // And this is for old KOS source compatability. Modified: kos/kernel/arch/dreamcast/include/dc/biosfont.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/biosfont.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/kernel/arch/dreamcast/include/dc/biosfont.h 2010-07-27 01:08:15 UTC (rev 675) @@ -6,7 +6,17 @@ */ +/** \file dc/biosfont.h + \brief BIOS font drawing functions. + This file provides support for utilizing the font built into the Dreamcast's + BIOS. These functions allow access to both the western character set and + Japanese characters. + + \author Dan Potter + \author Kazuaki Matsumoto +*/ + #ifndef __DC_BIOSFONT_H #define __DC_BIOSFONT_H @@ -16,20 +26,112 @@ #include <arch/types.h> /* Constants for the function below */ -#define BFONT_CODE_ISO8859_1 0 /* DEFAULT */ -#define BFONT_CODE_EUC 1 -#define BFONT_CODE_SJIS 2 +#define BFONT_CODE_ISO8859_1 0 /**< \brief ISO-8859-1 (western) charset */ +#define BFONT_CODE_EUC 1 /**< \brief EUC-JP charset */ +#define BFONT_CODE_SJIS 2 /**< \brief Shift-JIS charset */ -/* Select an encoding for Japanese (or disable) */ +/** \brief Set the font encoding. + + This function selects the font encoding that is used for the font. This + allows you to select between the various character sets available. + + \param enc The character encoding in use + \see BFONT_CODE_ISO8859_1 + \see BFONT_CODE_EUC + \see BFONT_CODE_SJIS +*/ void bfont_set_encoding(int enc); +/** \brief Find an ISO-8859-1 character in the font. + + This function retrieves a pointer to the font data for the specified + character in the font, if its available. Generally, you will not have to + use this function, use one of the bfont_draw_* functions instead. + + \param ch The character to look up + \return A pointer to the raw character data +*/ uint8 *bfont_find_char(int ch); + +/** \brief Find an full-width Japanese character in the font. + + This function retrieves a pointer to the font data for the specified + character in the font, if its available. Generally, you will not have to + use this function, use one of the bfont_draw_* functions instead. + + This function deals with full-width kana and kanji. + + \param ch The character to look up + \return A pointer to the raw character data +*/ uint8 *bfont_find_char_jp(int ch); + +/** \brief Find an half-width Japanese character in the font. + + This function retrieves a pointer to the font data for the specified + character in the font, if its available. Generally, you will not have to + use this function, use one of the bfont_draw_* functions instead. + + This function deals with half-width kana only. + + \param ch The character to look up + \return A pointer to the raw character data +*/ uint8 *bfont_find_char_jp_half(int ch); +/** \brief Draw a single character to a buffer. + + This function draws a single character in the set encoding to the given + buffer. Calling this is equivalent to calling bfont_draw_thin() with 0 for + the final parameter. + + \param buffer The buffer to draw to (at least 12 x 24 uint16s) + \param bufwidth The width of the buffer in pixels + \param opaque If non-zero, overwrite blank areas with black, + otherwise do not change them from what they are + \param c The character to draw +*/ void bfont_draw(uint16 *buffer, int bufwidth, int opaque, int c); + +/** \brief Draw a single thin character to a buffer. + + This function draws a single character in the set encoding to the given + buffer. This only works with ISO-8859-1 characters and half-width kana. + + \param buffer The buffer to draw to (at least 12 x 24 uint16s) + \param bufwidth The width of the buffer in pixels + \param opaque If non-zero, overwrite blank areas with black, + otherwise do not change them from what they are + \param c The character to draw + \param iskana Set to 1 if the character is a kana, 0 if ISO-8859-1 +*/ void bfont_draw_thin(uint16 *buffer, int bufwidth, int opaque, int c, int iskana); + +/** \brief Draw a single wide character to a buffer. + + This function draws a single character in the set encoding to the given + buffer. This only works with full-width kana and kanji. + + \param buffer The buffer to draw to (at least 24 x 24 uint16s) + \param bufwidth The width of the buffer in pixels + \param opaque If non-zero, overwrite blank areas with black, + otherwise do not change them from what they are + \param c The character to draw +*/ void bfont_draw_wide(uint16 *buffer, int bufwidth, int opaque, int c); + +/** \brief Draw a full string to a buffer. + + This function draws a NUL-terminated string in the set encoding to the given + buffer. This will automatially handle mixed half and full-width characters + if the encoding is set to one of the Japanese encodings. + + \param buffer The buffer to draw to + \param width The width of the buffer in pixels + \param opaque If non-zero, overwrite blank areas with black, + otherwise do not change them from what they are + \param str The string to draw +*/ void bfont_draw_str(uint16 *buffer, int width, int opaque, char *str); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/ubc.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/ubc.h 2010-07-20 20:05:07 UTC (rev 674) +++ kos/kernel/arch/dreamcast/include/dc/ubc.h 2010-07-27 01:08:15 UTC (rev 675) @@ -5,7 +5,14 @@ */ +/** \file dc/ubc.h + \brief User-break controller support. + This file defines some functionality for using the SH4 UBC. + + \author Dan Potter +*/ + #ifndef __DC_UBC_H #define __DC_UBC_H @@ -15,19 +22,27 @@ #include <arch/types.h> /* From the SH-4 PDF */ -#define BARA (*((vuint32*)0xFF200000)) -#define BASRA (*((vuint8*)0xFF000014)) -#define BAMRA (*((vuint8*)0xFF200004)) -#define BBRA (*((vuint16*)0xFF200008)) -#define BARB (*((vuint32*)0xFF20000C)) -#define BASRB (*((vuint8*)0xFF000018)) -#define BAMRB (*((vuint8*)0xFF200010)) -#define BBRB (*((vuint16*)0xFF200014)) -#define BRCR (*((vuint16*)0xFF200020)) +/** \defgroup ubc_regs UBC Registers + These registers are as documented in the SH4 manual. Consult it for more + information. + + @{ +*/ +#define BARA (*((vuint32*)0xFF200000)) /**< \brief BARA register. */ +#define BASRA (*((vuint8*)0xFF000014)) /**< \brief BASRA register. */ +#define BAMRA (*((vuint8*)0xFF200004)) /**< \brief BAMRA register. */ +#define BBRA (*((vuint16*)0xFF200008)) /**< \brief BBRA register. */ +#define BARB (*((vuint32*)0xFF20000C)) /**< \brief BARB register. */ +#define BASRB (*((vuint8*)0xFF000018)) /**< \brief BASRB register. */ +#define BAMRB (*((vuint8*)0xFF200010)) /**< \brief BAMRB register. */ +#define BBRB (*((vuint16*)0xFF200014)) /**< \brief BBRB register. */ +#define BRCR (*((vuint16*)0xFF200020)) /**< \brief BRCR register. */ +/** @} */ + /* These are inlined to avoid complications with using them */ -/* Pause after setting UBC parameters */ +/** \brief Pause after setting UBC parameters. */ static inline void ubc_pause() { __asm__ __volatile__("nop\n" "nop\n" @@ -42,14 +57,16 @@ "nop\n"); } -/* Disable all UBC breakpoints */ +/** \brief Disable all UBC breakpoints. */ static inline void ubc_disable_all() { BBRA = 0; BBRB = 0; ubc_pause(); } -/* Set a UBC data-write breakpoint at the given address */ +/** \brief Set a UBC data-write breakpoint at the given address. + \param address The address to set the breakpoint at +*/ static inline void ubc_break_data_write(uint32 address) { BASRA = 0; /* ASID = 0 */ BARA = address; /* Break address */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-20 20:05:13
|
Revision: 674 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=674&view=rev Author: ljsebald Date: 2010-07-20 20:05:07 +0000 (Tue, 20 Jul 2010) Log Message: ----------- More Doxygen comments, and some cleanup on existing ones. Modified Paths: -------------- kos/include/arpa/inet.h kos/include/kos/cdefs.h kos/include/kos/cond.h kos/include/kos/dbgio.h kos/include/kos/exports.h kos/include/kos/fs_ramdisk.h kos/include/kos/fs_romdisk.h kos/include/kos/fs_socket.h kos/include/kos/genwait.h kos/include/kos/iovec.h kos/include/kos/limits.h Modified: kos/include/arpa/inet.h =================================================================== --- kos/include/arpa/inet.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/arpa/inet.h 2010-07-20 20:05:07 UTC (rev 674) @@ -29,26 +29,26 @@ #include <inttypes.h> /** \brief Convert a 32-bit value from host byte order to network byte order. - \param value The value to convert. - \return value converted to network byte order. + \param value The value to convert. + \return value converted to network byte order. */ uint32_t htonl(uint32_t value); /** \brief Convert a 32-bit value from network byte order to host byte order. - \param value The value to convert. - \return value converted to host byte order. + \param value The value to convert. + \return value converted to host byte order. */ uint32_t ntohl(uint32_t value); /** \brief Convert a 16-bit value from host byte order to network byte order. - \param value The value to convert. - \return value converted to network byte order. + \param value The value to convert. + \return value converted to network byte order. */ uint16_t htons(uint16_t value); /** \brief Convert a 16-bit value from network byte order to host byte order. - \param value The value to convert. - \return value converted to host byte order. + \param value The value to convert. + \return value converted to host byte order. */ uint16_t ntohs(uint16_t value); @@ -58,9 +58,9 @@ address to an in_addr_t for use in a struct in_addr. This function supports all POSIX-required formats for the representation of the address. - \param cp A string representation of an IPv4 address. - \return The binary representation of the requested IPv4 address. - (in_addr_t)(-1) is returned on error. + \param cp A string representation of an IPv4 address. + \return The binary representation of the requested IPv4 + address. (in_addr_t)(-1) is returned on error. */ in_addr_t inet_addr(const char *cp); @@ -75,10 +75,10 @@ address (255.255.255.255). This version actually distinguishes between that address and invalid addresses. - \param cp A string representation of an IPv4 address. - \param pin The destination for the conversion. - \retval 0 An invalid IPv4 address was given. - \retval 1 Upon successful conversion. + \param cp A string representation of an IPv4 address. + \param pin The destination for the conversion. + \retval 0 An invalid IPv4 address was given. + \retval 1 Upon successful conversion. */ int inet_aton(const char *cp, struct in_addr *pin); @@ -95,15 +95,18 @@ function that you should actually use to convert addresses from strings to binary in new code, rather than inet_addr or inet_aton. - \param af The address family that src is an address in. The only - supported value is AF_INET (IPv4). - \param src A string representation of the address. - \param dst Storage for the result. For AF_INET, this must be at least - 32-bits in size (the function treats it as a struct - in_addr). - \retval -1 af is unsupported (errno is set to EAFNOSUPPORT). - \retval 0 An invalid address was given. - \retval 1 Upon successful conversion. + \param af The address family that src is an address in. The + only supported value currently is AF_INET (IPv4). + \param src A string representation of the address. + \param dst Storage for the result. For AF_INET, this must be at + least 32-bits in size (the function treats it as a + struct in_addr). + \retval -1 af is unsupported. + \retval 0 An invalid address was given. + \retval 1 Upon successful conversion. + + \par Error Conditions: + \em EAFNOSUPPORT - the specified address family is unsupported */ int inet_pton(int af, const char *src, void *dst); @@ -115,16 +118,18 @@ convert a binary representation of an IP address to a string. Note that this function, like all of KOS' network system, does not support IPv6. - \param af The address family that src is in. The only supported value - is AF_INET (IPv4). - \param src A binary representation of an IP address. - \param dst Storage for the resulting string. This string should be at - least 16-bytes long for IPv4. - \param size The length of dst. - \retval NULL Upon failed conversion. errno will be set to EAFNOSUPPORT - if af was invalid or ENOSPC if the buffer was not of an - adequate length. - \retval dst Upon successful conversion. + \param af The address family that src is in. The only + supported value currently is AF_INET (IPv4). + \param src A binary representation of an IP address. + \param dst Storage for the resulting string. This string should + be at least 16-bytes long for IPv4. + \param size The length of dst. + \retval NULL Upon failed conversion. + \retval dst Upon successful conversion. + + \par Error Conditions: + \em EAFNOSUPPORT - the specified address family is unsupported \n + \em ENOSPC - the size given is insufficient */ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); @@ -135,8 +140,9 @@ is non-reentrant (not thread-safe), and will always only support IPv4 addresses. It is suggested to use inet_ntop in any new code. - \param addr The address to convert. - \return A string representation of addr (in dotted-decimal form). + \param addr The address to convert. + \return A string representation of addr (in dotted-decimal + form). */ char *inet_ntoa(struct in_addr addr); Modified: kos/include/kos/cdefs.h =================================================================== --- kos/include/kos/cdefs.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/cdefs.h 2010-07-20 20:05:07 UTC (rev 674) @@ -6,6 +6,15 @@ Based loosely around some stuff in BSD's sys/cdefs.h */ +/** \file kos/cdefs.h + \brief Potentially useful definitions for C Programs. + + This file contains definitions of various __attribute__ directives in + shorter forms for use in programs (to aid in optimization, mainly). + + \author Dan Potter +*/ + #ifndef __KOS_CDEFS_H #define __KOS_CDEFS_H @@ -23,19 +32,45 @@ #endif /* _arch_ps2 */ /* Special function/variable attributes */ + +/** \brief Identify a function that will never return. */ #define __noreturn __attribute__((__noreturn__)) + +/** \brief Identify a function that has no side effects other than its return, + and only uses its arguments for any work. */ #define __pure __attribute__((__const__)) + +/** \brief Identify a function or variable that may be unused. */ #define __unused __attribute__((__unused__)) +/** \brief Alias for \ref __noreturn. For BSD compatibility. */ #define __dead2 __noreturn /* BSD compat */ + +/** \brief Alias for \ref __pure. Fore BSD compatibility. */ #define __pure2 __pure /* ditto */ /* Printf/Scanf-like declaration */ +/** \brief Identify a function as accepting formatting like printf(). + + Using this macro allows GCC to typecheck calls to printf-like functions, + which can aid in finding mistakes. + + \param fmtarg The argument number (1-based) of the format string. + \param firstvararg The argument number of the first vararg (the ...). +*/ #define __printflike(fmtarg, firstvararg) \ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +/** \brief Identify a function as accepting formatting like scanf(). + + Using this macro allows GCC to typecheck calls to scanf-like functions, + which can aid in finding mistakes. + + \param fmtarg The argument number (1-based) of the format string. + \param firstvararg The argument number of the first vararg (the ...). +*/ #define __scanflike(fmtarg, firstvararg) \ - __attribute__((__format__ (__printf__, fmtarg, firstvararg))) + __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) /* GCC macros for special cases */ /* #if __GNUC__ == */ Modified: kos/include/kos/cond.h =================================================================== --- kos/include/kos/cond.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/cond.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,37 @@ */ +/** \file kos/cond.h + \brief Condition variables. + + This file contains the definition of a Condition Variable. Condition + Variables (or condvars for short) are used with a mutex to act as a lock and + checkpoint pair for threads. + + Basically, things work as follows (for the thread doing work): + \li The associated mutex is locked. + \li A predicate is checked to see if its safe to do something. + \li If it is not safe, you call cond_wait(), which releases the mutex. + \li When cond_wait() returns, the mutex is reaquired, and work can go on. + \li Update any predicates so that we konw that the work is done, and unlock + the mutex. + + Meanwhile, the thread updating the condition works as follows: + \li Lock the mutex associated with the condvar. + \li Produce work to be done. + \li Call cond_signal() (with the associated mutex still locked), so that any + threads waiting on the condvar will know they can continue on when the + mutex is released, also update any predicates that say whether work can + be done. + \li Unlock the mutex so that worker threads can acquire the mutex and do + whatever work needs to be done. + + Condition variables can be quite useful when used properly, and provide a + fairly easy way to wait for work to be ready to be done. + + \author Dan Potter +*/ + #ifndef __KOS_COND_H #define __KOS_COND_H @@ -17,60 +48,153 @@ #include <kos/mutex.h> #include <kos/recursive_lock.h> -/* Condition structure */ +/** \brief Condition variable. + + There are no public members of this structure for you to actually do + anything with in your code, so don't try. + + \headerfile kos/cond.h +*/ typedef struct condvar { + /* \cond */ /* List entry for the global list of condvars */ LIST_ENTRY(condvar) g_list; + /* \endcond */ } condvar_t; +/* \cond */ LIST_HEAD(condlist, condvar); +/* \endcond */ -/* Allocate a new condvar. Sets errno to ENOMEM on failure. */ +/** \brief Allocate a new condition variable. + + This function allocates and initializes a new condition variable for use. + + \return The created condvar on success. NULL is returned on + failure, and errno is set as appropriate. + + \par Error Conditions: + \em ENOMEM - Out of memory +*/ condvar_t *cond_create(); -/* Free a condvar */ +/** \brief Free a condition variable. + + This function frees a condition variable, releasing all memory associated + with it (but not with the mutex that is associated with it). This will also + wake all threads waiting on the condition. +*/ void cond_destroy(condvar_t *cv); -/* Wait on a condvar; if there is an associated mutex to unlock - while waiting, then pass that as well. Returns -1 on error. - EPERM - called inside interrupt - EINTR - wait was interrupted */ +/** \brief Wait on a condition variable. + + This function will wait on the condition variable, unlocking the mutex and + putting the calling thread to sleep as one atomic operation. The wait in + this function has no timeout, and will sleep forever if the condition is not + signalled. + + \param cv The condition to wait on. + \param m The associated mutex. + \retval 0 On success. + \retval -1 On error, sets errno as appropriate. + + \par Error Conditions: + \em EPERM - Called inside an interrupt \n + \em EINTR - Was interrupted +*/ int cond_wait(condvar_t *cv, mutex_t * m); -/* Same as above, but uses a recursive lock instead of a mutex. - Note that using this is a really bad idea, since if the lock hasn't - been completely unlocked by the single unlock that happens in this - function, you will likely end up with a deadlock. This was only - added for support for GCC's C++0x threading support. */ +/** \brief Wait on a condition variable, using a recursive_lock_t. + + This function acts exactly like the cond_wait() function, except instead of + a mutex_t as its lock, it uses a recursive_lock_t. Generally, this should + not be preferred, as deadlock may occur if the calling thread has locked + the lock more than once (since this function only unlocks it once). This was + added specifically because it was required for GCC's C++0x threading code. + + \param cv The condition to wait on. + \param l The associated lock. + \retval 0 On success. + \retval -1 On error, sets errno as appropriate. + + \par Error Conditions: + \em EPERM - Called inside an interrupt \n + \em EINTR - Was interrupted. + + \author Lawrence Sebald +*/ int cond_wait_recursive(condvar_t *cv, recursive_lock_t *l); -/* Wait on a condvar; if there is an associated mutex to unlock - while waiting, then pass that as well. If more than 'timeout' - milliseconds passes and we still haven't been signaled, return - an error code (-1). Return success (0) when we are woken normally. - Note: if 'timeout' is zero, this call is equivalent to - cond_wait above. - EPERM - called inside interrupt - EAGAIN - timed out - EINTR - was interrupted */ +/** \brief Wait on a condition variable with a timeout. + + This function will wait on the condition variable, unlocking the mutex and + putting the calling thread to sleep as one atomic operation. If the timeout + elapses before the condition is signalled, this function will return error. + If a timeout of 0 is given, the call is equivalent to cond_wait() (there is + no timeout). + + \param cv The condition to wait on. + \param m The associated mutex. + \param timeout The number of milliseconds before timeout. + \retval 0 On success. + \retval -1 On error, sets errno as appropriate. + + \par Error Conditions: + \em EPERM - Called inside an interrupt \n + \em EINTR - Was interrupted \n + \em EAGAIN - timed out +*/ int cond_wait_timed(condvar_t *cv, mutex_t * m, int timeout); -/* Save as above, but uses a recursive lock instead of a mutex. - The note about deadlocks with cond_wait_recursive above still - applies here. */ +/** \brief Wait on a condition variable with a timeout, using a recursive lock. + + This function will wait on the condition variable, unlocking the lock and + putting the calling thread to sleep as one atomic operation. If the timeout + elapses before the condition is signalled, this function will return error. + If a timeout of 0 is given, the call is equivalent to cond_wait() (there is + no timeout). The rant about cond_wait_recursive() being evil applies here + as well. + + \param cv The condition to wait on. + \param l The associated recursive lock. + \param timeout The number of milliseconds before timeout. + \retval 0 On success. + \retval -1 On error, sets errno as appropriate. + + \par Error Conditions: + \em EPERM - Called inside an interrupt \n + \em EINTR - Was interrupted \n + \em EAGAIN - timed out + + \author Lawrence Sebald +*/ int cond_wait_timed_recursive(condvar_t *cv, recursive_lock_t *l, int timeout); -/* Signal a single thread waiting on the condvar; you should be - holding any associated mutex before doing this! */ +/** \brief Signal a single thread waiting on the condition variable. + + This function will wake up a single thread that is waiting on the condition. + The calling thread should be holding the associated mutex or recursive lock + before calling this to guarantee sane behavior. + + \param cv The condition to signal. +*/ void cond_signal(condvar_t *cv); -/* Signal all threads waiting on the condvar; you should be holding - any associated mutex before doing this! */ +/** \brief Signal all threads waiting on the condition variable. + + This function will wake up all threads that are waiting on the condition. + The calling thread should be holding the associated mutex or recursive lock + before calling this to guarantee sane behavior. + + \param cv The condition to signal. +*/ void cond_broadcast(condvar_t *cv); /* Init / shutdown */ +/* \cond */ int cond_init(); void cond_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/include/kos/dbgio.h =================================================================== --- kos/include/kos/dbgio.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/dbgio.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,17 @@ */ +/** \file kos/dbgio.h + \brief Debug I/O. + + This file contains the Debug I/O system, which abstracts things so that + various types of debugging tools can be used by programs in KOS. Included + among these tools is the dcload console (dcload-serial, dcload-ip, and + fs_dclsocket), a raw serial console, and a framebuffer based console. + + \author Dan Potter +*/ + #ifndef __KOS_DBGIO_H #define __KOS_DBGIO_H @@ -13,107 +24,211 @@ #include <arch/types.h> -/** This struct represents a single dbgio interface. This should represent +/** \brief Debug I/O Interface. + + This struct represents a single dbgio interface. This should represent a generic pollable console interface. We will store an ordered list of these statically linked into the program and fall back from one to the next until one returns true for detected(). Note that the last device in - this chain is the null console, which will always return true. */ + this chain is the null console, which will always return true. + + \headerfile kos/dbgio.h +*/ typedef struct dbgio_handler { - /** Name of the dbgio handler */ - const char * name; + /** \brief Name of the dbgio handler */ + const char * name; - /** Returns 1 if the device is available and usable, or 0 if it - appears not to be. */ - int (*detected)(); + /** \brief Detect this debug interface. + \retval 1 If the device is available and useable + \retval 0 If the device is unavailable + */ + int (*detected)(); - /** Init the interface with default parameters. */ - int (*init)(); + /** \brief Initialize this debug interface with default parameters. + \retval 0 On success + \retval -1 On failure + */ + int (*init)(); - /** Shut down the interface */ - int (*shutdown)(); + /** \brief Shutdown this debug interface. + \retval 0 On success + \retval -1 On failure + */ + int (*shutdown)(); - /** Set polled/IRQ usage */ - int (*set_irq_usage)(int mode); + /** \brief Set either polled or IRQ usage for this interface. + \param mode 1 for IRQ-based usage, 0 for polled I/O + \retval 0 On success + \retval -1 On failure + */ + int (*set_irq_usage)(int mode); - /** Read one char from the console or -1 if there's nothing to read, - or an error condition exists (check errno). */ - int (*read)(); - - /** Write one char to the console (may need to call flush()). - Returns the number of chars written or -1 on error. */ - int (*write)(int c); + /** \brief Read one character from the console. + \retval 0 On success + \retval -1 On failure (set errno as appropriate) + */ + int (*read)(); - /** Flush any queued written bytes. Returns -1 on error. */ - int (*flush)(); + /** \brief Write one character to the console. + \param c The character to write + \retval 1 On success + \retval -1 On error (set errno as appropriate) + \note Interfaces may require a call to flush() before the + output is actually flushed to the console. + */ + int (*write)(int c); - /** Send an entire buffer. Returns the number of chars written or - -1 on error. If xlat is non-zero, then newline transformations - may occur. */ - int (*write_buffer)(const uint8 *data, int len, int xlat); + /** \brief Flush any queued output. + \retval 0 On success + \retval -1 On error (set errno as appropriate) + */ + int (*flush)(); - /** Read a buffer (block). Returns the number of chars read or - -1 on error. */ - int (*read_buffer)(uint8 *data, int len); + /** \brief Write an entire buffer of data to the console. + \param data The buffer to write + \param len The length of the buffer + \param xlat If non-zero, newline transformations may occur + \return Number of characters written on success, or -1 on + failure (set errno as appropriate) + */ + int (*write_buffer)(const uint8 *data, int len, int xlat); + + /** \brief Read an entire buffer of data from the console. + \param data The buffer to read into + \param len The length of the buffer + \return Number of characters read on success, or -1 on + failure (set errno as appropriate) + */ + int (*read_buffer)(uint8 *data, int len); } dbgio_handler_t; +/** \cond */ /* These two should be initialized in arch. */ extern dbgio_handler_t * dbgio_handlers[]; extern int dbgio_handler_cnt; /* This is defined by the shared code, in case there's no valid handler. */ extern dbgio_handler_t dbgio_null; +/** \endcond */ -/** Manually select a new dbgio interface by name. Returns 0 on success or - -1 on error. Note that even if the given device isn't detected, this - will still let you select it. */ +/** \brief Select a new dbgio interface by name. + + This function manually selects a new dbgio interface by name. This function + will allow you to select a device, even if it is not detected. + + \param name The dbgio interface to select + \retval 0 On success + \retval -1 On error + + \par Error Conditions: + \em ENODEV - The specified device could not be initialized +*/ int dbgio_dev_select(const char * name); -/** Returns the name of the currently selected device. */ +/** \brief Fetch the name of the currently selected dbgio interface. + \return The name of the current dbgio interface (or NULL if + no device is selected) +*/ const char * dbgio_dev_get(); -/** Initialize the dbgio console. The device selection process is as - described above. */ +/** \brief Initialize the dbgio console. + + This function is called internally, and shouldn't need to be called by any + user programs. + + \retval 0 On success + \retval -1 On error + \par Error Conditions: + \em ENODEV - No devices could be detected/initialized +*/ int dbgio_init(); -/** Set IRQ usage - we default to polled */ +/** \brief Set IRQ usage. + + The dbgio system defaults to polled usage. Some devices may not support IRQ + mode at all. + + \param mode The mode to use + \retval 0 On success + \retval -1 On error (errno should be set as appropriate) +*/ int dbgio_set_irq_usage(int mode); + +/** \brief Polled I/O mode. + \see dbgio_set_irq_usage() +*/ #define DBGIO_MODE_POLLED 0 + +/** \brief IRQ-based I/O mode. + \see dbgio_set_irq_usage() +*/ #define DBGIO_MODE_IRQ 1 -/** Read one char from the console or -1 if there's nothing to read, - or an error condition exists (check errno). */ +/** \brief Read one character from the console. + \retval 0 On success + \retval -1 On error (errno should be set as appropriate) +*/ int dbgio_read(); -/** Write one char to the console (may need to call flush()). - Returns the number of chars written or -1 on error. */ +/** \brief Write one character to the console. + \param c The character to write + \retval 1 On success (number of characters written) + \retval -1 On error (errno should be set as appropriate) + \note Interfaces may require a call to flush() before the + output is actually flushed to the console. +*/ int dbgio_write(int c); -/** Flush any queued written bytes. Returns -1 on error. */ +/** \brief Flush any queued output. + \retval 0 On success + \retval -1 On error (errno should be set as appropriate) +*/ int dbgio_flush(); -/** Send an entire buffer. Returns the number of chars written or - -1 on error. */ +/** \brief Write an entire buffer of data to the console. + \param data The buffer to write + \param len The length of the buffer + \return Number of characters written on success, or -1 on + failure (errno should be set as appropriate) +*/ int dbgio_write_buffer(const uint8 *data, int len); -/** Read a buffer (block). Returns the number of chars read or - -1 on error. */ +/** \brief Read an entire buffer of data from the console. + \param data The buffer to read into + \param len The length of the buffer + \return Number of characters read on success, or -1 on + failure (errno should be set as appropriate) +*/ int dbgio_read_buffer(uint8 *data, int len); -/** Send an entire buffer. Returns the number of chars written or - -1 on error. Newline translations may occur. */ +/** \brief Write an entire buffer of data to the console (potentially with + newline transformations). + \param data The buffer to write + \param len The length of the buffer + \return Number of characters written on success, or -1 on + failure (errno should be set as appropriate) +*/ int dbgio_write_buffer_xlat(const uint8 *data, int len); -/** Send a string (null-terminated). Returns the number of chars - written or -1 on error. */ +/** \brief Write a NUL-terminated string to the console. + \param str The string to write + \return Number of characters written on success, or -1 on + failure (errno should be set as appropriate) +*/ int dbgio_write_str(const char *str); -/** Disable debug I/O globally */ +/** \brief Disable debug I/O globally. */ void dbgio_disable(); -/** Enable debug I/O globally */ +/** \brief Enable debug I/O globally. */ void dbgio_enable(); -/** Printf functionality */ +/** \brief Built-in debug I/O printf function. + \param fmt A printf() style format string + \param ... Format arguments + \return The number of bytes written, or <0 on error (errno + should be set as appropriate) +*/ int dbgio_printf(const char *fmt, ...) __printflike(1, 2); __END_DECLS Modified: kos/include/kos/exports.h =================================================================== --- kos/include/kos/exports.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/exports.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,16 @@ */ +/** \file kos/exports.h + \brief Kernel exported symbols support. + + This file contains support related to dynamic linking of the kernel of KOS. + The kernel (at compile time) produces a list of exported symbols, which can + be looked through using the funtionality in this file. + + \author Dan Potter +*/ + #ifndef __KOS_EXPORTS_H #define __KOS_EXPORTS_H @@ -13,35 +23,48 @@ #include <arch/types.h> -/* This struct holds one export symbol that will be patched into - loaded ELF files. */ +/** \brief A single export symbol. + + This structure holds a single symbol that has been exported from the kernel. + These will be patched into loaded ELF binaries at load time. + + \headerfile kos/exports.h +*/ typedef struct export_sym { - const char * name; - ptr_t ptr; + const char * name; /**< \brief The name of the symbol. */ + ptr_t ptr; /**< \brief A pointer to the symbol. */ } export_sym_t; +/** \cond */ /* These are the platform-independent exports */ extern export_sym_t kernel_symtab[]; /* And these are the arch-specific exports */ extern export_sym_t arch_symtab[]; +/** \endcond */ #ifndef __EXPORTS_FILE #include <kos/nmmgr.h> -/* This struct defines a symbol table "handler" for nmmgr. */ + +/** \brief A symbol table "handler" for nmmgr. + \headerfile kos/exports.h +*/ typedef struct symtab_handler { - /* Name manager handler header */ - struct nmmgr_handler nmmgr; - - /* Location of the first entry */ - export_sym_t * table; + struct nmmgr_handler nmmgr; /**< \brief Name manager handler header */ + export_sym_t * table; /**< \brief Location of the first entry */ } symtab_handler_t; #endif -/* Setup our initial exports */ +/** \brief Setup initial kernel exports. + \retval 0 On success + \retval -1 On error +*/ int export_init(); -/* Look up a symbol by name. Returns the struct. */ +/** \brief Look up a symbol by name. + \param name The symbol to look up + \return The export structure, or NULL on failure +*/ export_sym_t * export_lookup(const char * name); __END_DECLS Modified: kos/include/kos/fs_ramdisk.h =================================================================== --- kos/include/kos/fs_ramdisk.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/fs_ramdisk.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,20 @@ */ +/** \file kos/fs_ramdisk.h + \brief RAM-based virtual file system. + + This file contains support for a ramdisk VFS. This VFS allows you to map + memory into files that will appear in /ram. Files in this VFS can grow as + large as memory allows, and there is full read/write support here. This is + useful, for (for instance) cacheing files read from the CD-ROM or for making + temporary files. + + You only have one ramdisk available, and its mounted on /ram. + + \author Dan Potter +*/ + #ifndef __KOS_FS_RAMDISK_H #define __KOS_FS_RAMDISK_H @@ -15,17 +29,39 @@ #include <kos/limits.h> #include <kos/fs.h> -/* Call this function to have the ramdisk fs take over a piece - of memory from you and turn it into a ramdisk file. This is handy - if you have some loaded object but need to use it as a file. - XXX Doesn't work with multiple ramdisks... do we care? */ +/** \brief Attach a block of memory as a file in the ramdisk. + + This function takes a block of memory and associates it with a file on the + ramdisk. This memory should be allocated with malloc(), as an unlink() of + the file will call free on the block of memory. The ramdisk then effectively + takes control of the block, and is responsible for it at that point. + + \param fn The name to give the new file + \param obj The block of memory to associate + \param size The size of the block of memory + \retval 0 On success + \retval -1 On failure +*/ int fs_ramdisk_attach(const char * fn, void * obj, size_t size); -/* Does the opposite of attach */ +/** \brief Detach a file from the ramdisk. + + This function retrieves the block of memory associated with the file, + removing it from the ramdisk. You are responsible for freeing obj when you + are done with it. + + \param fn The name of the file to look for. + \param obj A pointer to return the address of the object in. + \param size A pointer to return the size of the object in. + \retval 0 On success + \retval -1 On failure +*/ int fs_ramdisk_detach(const char * fn, void ** obj, size_t * size); +/** \cond */ int fs_ramdisk_init(); int fs_ramdisk_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/kos/fs_romdisk.h =================================================================== --- kos/include/kos/fs_romdisk.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/fs_romdisk.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,22 @@ */ +/** \file kos/fs_romdisk.h + \brief ROMFS virtual file system. + + This file contains support for the romdisk VFS. This VFS allows you to make + Linux-style ROMFS images and either embed them into your binary or load them + at runtime from some other source (such as a CD-ROM). These images are made + with the genromfs program that is included in the utils portion of the tree. + + You can choose to automount one ROMFS image by embedding it into your binary + and using the appropriate KOS_INIT_FLAGS() setting. The embedded ROMFS will + mount itself on /rom. You can also mount additional images that you load + from some other source on whatever mountpoint you want. + + \author Dan Potter +*/ + #ifndef __KOS_FS_ROMDISK_H #define __KOS_FS_ROMDISK_H @@ -15,26 +31,51 @@ #include <kos/limits.h> #include <kos/fs.h> +/** \brief The maximum number of files that can be open at a time. */ #define MAX_RD_FILES 16 +/** \cond */ /* Initialize the file system */ int fs_romdisk_init(); /* De-init the file system; also unmounts any mounted images. */ int fs_romdisk_shutdown(); +/** \endcond */ /* NOTE: the mount/unmount are _not_ thread safe as regards doing multiple mounts/unmounts in different threads at the same time, and they don't check for open files currently either. Caveat emptor! */ -/* Mount a romdisk image; must have called fs_romdisk_init() earlier. - Also note that we do _not_ take ownership of the image data if - own_buffer is 0, so if you malloc'd that buffer, you must - also free it after the unmount. If own_buffer is non-zero, then - we free the buffer when it is unmounted. */ +/** \brief Mount a ROMFS image as a new filesystem. + + This function will mount a ROMFS image that has been loaded into memory to + the specified mountpoint. + + \param mountpoint The directory to mount this romdisk on + \param img The ROMFS image + \param own_buffer If 0, you are still responsible for img, and must + free it if appropriate. If non-zero, img will be + freed when it is unmounted + \retval 0 On success + \retval -1 On error +*/ int fs_romdisk_mount(const char * mountpoint, const uint8 *img, int own_buffer); -/* Unmount a romdisk image */ +/** \brief Unmount a ROMFS image. + + This function unmounts a ROMFS image that has been previously mounted with + fs_romdisk_mount(). This function does not check for open files on the fs, + so make sure that all files have been closed before calling it. If the VFS + owns the buffer (own_buffer was non-zero when you called the mount function) + then this function will also free the buffer. + + \param mountpoint The ROMFS to unmount + \retval 0 On success + \retval -1 On error + + \par Error Conditions: + \em ENOENT - no such ROMFS was mounted +*/ int fs_romdisk_unmount(const char * mountpoint); __END_DECLS Modified: kos/include/kos/fs_socket.h =================================================================== --- kos/include/kos/fs_socket.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/fs_socket.h 2010-07-20 20:05:07 UTC (rev 674) @@ -122,12 +122,12 @@ called, and will be cleaned up by fs_socket if an error is returned from the handler (a return value of -1). - \param s The socket structure to initialize. - \param domain Domain of the socket. - \param type Type of the socket. - \param protocol Protocol of the socket. - \retval -1 On error (errno should be set appropriately). - \retval 0 On success. + \param s The socket structure to initialize + \param domain Domain of the socket + \param type Type of the socket + \param protocol Protocol of the socket + \retval -1 On error (errno should be set appropriately) + \retval 0 On success */ int (*socket)(net_socket_t *s, int domain, int type, int protocol); @@ -138,7 +138,7 @@ with the close system call. There are no errors defined for this function. - \param s The socket to close. + \param s The socket to close */ void (*close)(net_socket_t *hnd); @@ -148,11 +148,11 @@ a socket created with this protocol. The semantics are the same as described in the documentation for that function. - \param s The socket to set flags on. - \param flags The flags to set. - \retval -1 On error (set errno appropriately). - \retval 0 On success. - \sa fs_socket_setflags + \param s The socket to set flags on + \param flags The flags to set + \retval -1 On error (set errno appropriately) + \retval 0 On success + \see fs_socket_setflags */ int (*setflags)(net_socket_t *s, int flags); @@ -161,11 +161,11 @@ This function should implement the ::accept() system call for the protocol. The semantics are exactly as expected for that function. - \param s The socket to accept a connection on. - \param addr The address of the incoming connection. - \param alen The length of the address. - \return A newly created socket for the incoming connection or -1 on - error (with errno set appropriately). + \param s The socket to accept a connection on + \param addr The address of the incoming connection + \param alen The length of the address + \return A newly created socket for the incoming connection + or -1 on error (with errno set appropriately) */ int (*accept)(net_socket_t *s, struct sockaddr *addr, socklen_t *alen); @@ -174,11 +174,11 @@ This function should implement the ::bind() system call for the protocol. The semantics are exactly as expected for that function. - \param s The socket to bind to the address. - \param addr The address to bind to. - \param alen The length of the address. - \retval -1 On error (set errno appropriately). - \retval 0 On success. + \param s The socket to bind to the address + \param addr The address to bind to + \param alen The length of the address + \retval -1 On error (set errno appropriately) + \retval 0 On success */ int (*bind)(net_socket_t *s, const struct sockaddr *addr, socklen_t alen); @@ -187,11 +187,11 @@ This function should implement the ::connect() system call for the protocol. The semantics are exactly as expected for that function. - \param s The socket to connect with. - \param addr The address to connect to. - \param alen The length of the address. - \retval -1 On error (with errno set appropriately). - \retval 0 On success. + \param s The socket to connect with + \param addr The address to connect to + \param alen The length of the address + \retval -1 On error (with errno set appropriately) + \retval 0 On success */ int (*connect)(net_socket_t *s, const struct sockaddr *addr, socklen_t alen); @@ -202,10 +202,10 @@ This function should implement the ::listen() system call for the protocol. The semantics are exactly as expected for that function. - \param s The socket to listen on. - \param backlog The number of connections to queue. - \retval -1 On error (with errno set appropriately). - \retval 0 On success. + \param s The socket to listen on + \param backlog The number of connections to queue + \retval -1 On error (with errno set appropriately) + \retval 0 On success */ int (*listen)(net_socket_t *s, int backlog); @@ -216,18 +216,18 @@ this function should implement the ::recv() system call, which will call this function with NULL for addr and alen. - \param s The socket to receive data on. - \param buffer The buffer to save data in. - \param len The length of the buffer. - \param flags Flags to the function. - \param addr Space to store the address that data came from (NULL - if this was called by ::recv()). - \param alen Space to store the length of the address (NULL if this - was called by ::recv()). - \retval -1 On error (set errno appropriately). - \retval 0 No outstanding data and the peer has disconnected - cleanly. - \retval n The number of bytes received (may be less than len). + \param s The socket to receive data on + \param buffer The buffer to save data in + \param len The length of the buffer + \param flags Flags to the function + \param addr Space to store the address that data came from (NULL + if this was called by ::recv()) + \param alen Space to store the length of the address (NULL if + this was called by ::recv()) + \retval -1 On error (set errno appropriately) + \retval 0 No outstanding data and the peer has disconnected + cleanly + \retval n T he number of bytes received (may be less than len) */ ssize_t (*recvfrom)(net_socket_t *s, void *buffer, size_t len, int flags, struct sockaddr *addr, socklen_t *alen); @@ -239,17 +239,17 @@ this function should implement the ::send() system call, which will call this function with NULL for addr and 0 for alen. - \param s The socket to send data on. - \param msg The data to send. - \param len The length of data to send. - \param flags Flags to the function. - \param addr The address to send data to (NULL if this was called by - ::send()). - \param alen The length of the address (0 if this was called by - ::send()). - \retval -1 On error (set errno appropriately). - \retval n The number of bytes actually sent (may be less than - len). + \param s The socket to send data on + \param msg The data to send + \param len The length of data to send + \param flags Flags to the function + \param addr The address to send data to (NULL if this was called + by ::send()) + \param alen The length of the address (0 if this was called by + ::send()) + \retval -1 On error (set errno appropriately) + \retval n The number of bytes actually sent (may be less than + len) */ ssize_t (*sendto)(net_socket_t *s, const void *msg, size_t len, int flags, const struct sockaddr *addr, socklen_t alen); @@ -259,10 +259,10 @@ This function should implement the ::shutdown() system call for the protocol. The semantics are exactly as expected for that function. - \param s The socket to shut down. - \param how What should be shut down on the socket. - \retval -1 On error (set errno appropriately). - \retval 0 On success. + \param s The socket to shut down + \param how What should be shut down on the socket + \retval -1 On error (set errno appropriately) + \retval 0 On success */ int (*shutdownsock)(net_socket_t *s, int how); } fs_socket_proto_t; @@ -283,19 +283,20 @@ flags available for use here are largely protocol dependent, and for UDP the only flag available is O_NONBLOCK. - \param sock The socket to operate on (returned from a call to the - function socket()). - \param flags The flags to set on the socket. - \retval -1 On error, and sets errno to EWOULDBLOCK if the function - would block while inappropriate to do so (i.e, in an - interrupt), EBADF if an invalid file descriptor was passed - in, ENOTSOCK if a file descriptor that is not a socket was - passed in, or EINVAL if an invalid flag was passed in. - \retval 0 On success. + \param sock The socket to operate on (returned from a call to the + function socket()) + \param flags The flags to set on the socket. + \retval -1 On error, and sets errno as appropriate + \retval 0 On success + + \par Error Conditions: + \em EWOULDBLOCK - if the function would block while inappropriate to \n + \em EBADF - if passed an invalid file descriptor \n + \em ENOTSOCK - if passed a file descriptor other than a socket \n + \em EINVAL - if an invalid flag was passed in */ int fs_socket_setflags(int sock, int flags); -/* Registration of protocols for fs_socket. */ /** \brief Add a new protocol for use with fs_socket. This function registers a protocol handler with fs_socket for use when @@ -305,8 +306,8 @@ This function is NOT safe to call inside an interrupt. - \param proto The new protocol handler to register. - \retval 0 On success (no error conditions are currently defined). + \param proto The new protocol handler to register + \retval 0 On success (no error conditions are currently defined) */ int fs_socket_proto_add(fs_socket_proto_t *proto); @@ -318,9 +319,9 @@ protocol to be removed (as they will not work properly once the handler has been removed). - \param proto The protocol handler to remove. - \retval -1 On error (This function does not directly change errno). - \retval 0 On success. + \param proto The protocol handler to remove + \retval -1 On error (This function does not directly change errno) + \retval 0 On success */ int fs_socket_proto_remove(fs_socket_proto_t *proto); Modified: kos/include/kos/genwait.h =================================================================== --- kos/include/kos/genwait.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/genwait.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,18 @@ */ +/** \file kos/genwait.h + \brief Generic wait system. + + The generic wait system in KOS, like many other portions of KOS, is based on + an idea from the BSD kernel. It allows you to sleep on any random object and + later wake up any threads that happen to be sleeping on thta object. All of + KOS' sync primatives (other than spinlocks) are based on this concept, and + it can be used for some fairly useful things. + + \author Dan Potter +*/ + #ifndef __KOS_GENWAIT_H #define __KOS_GENWAIT_H @@ -14,37 +26,84 @@ #include <sys/queue.h> #include <kos/thread.h> -/* Sleep on the object "obj". The sleep status will be listed in any - textual displays as "mesg". If "timeout" is non-zero, then the thread - will be woken again after timeout milliseconds even if it hasn't - been signaled manually. If "callback" is non-NULL, then the given - function will be called with "obj" as its parameter if the wait - times out (but before the thread is re-scheduled). */ +/** \brief Sleep on an object. + + This function sleeps on the specified object. You are not allowed to call + this function inside an interrupt. + + \param obj The object to sleep on + \param mesg A message to show in the status + \param timeout If not woken before this many milliseconds have + passed, wake up anyway + \param callback If non-NULL, call this function with obj as its + argument if the wait times out (but before the + calling thread has been woken back up) + \retval 0 On successfully being woken up (not by timeout) + \retval -1 On error or being woken by timeout + + \par Error Conditions: + \em EAGAIN - on timeout +*/ int genwait_wait(void * obj, const char * mesg, int timeout, void (*callback)(void *)); /* Wake up N threads waiting on the given object. If cnt is <=0, then we wake all threads. Returns the number of threads actually woken. */ +/** \brief Wake up a number of threads sleeping on an object. + + This function wakes up the specified number of threads sleeping on the + object specified. + + \param obj The object to wake threads that are sleeping on it + \param cnt The number of threads to wake, if <= 0, wake all + \return The number of threads woken +*/ int genwait_wake_cnt(void * obj, int cnt); -/* Wake up all threads waiting on the given object. */ +/** \brief Wake up all threads sleeping on an object. + + This function simply calls genwait_wake_cnt(obj, -1). + + \param obj The thread to wake threads that are sleeping on it + \see genwait_wake_cnt() +*/ void genwait_wake_all(void * obj); -/* Wake up one thread waiting on the given object. */ +/** \brief Wake up one thread sleeping on an object. + + This function simply calls genwait_wake_cnt(obj, 1). + + \param obj The thread to wake threads that are sleeping on it + \see genwait_wake_cnt() +*/ void genwait_wake_one(void * obj); -/* Called by the scheduler to look for timed out genwait_wait calls. - Pass the current system clock as "now". */ +/** \brief Look for timed out genwait_wait() calls. + + There should be no reason you need to call this function, it is called + internally by the scheduler for you. + + \param now The current system time, in milliseconds since boot +*/ void genwait_check_timeouts(uint64 now); -/* Returns the time of the next timeout event. If there are no pending - timeout events, then we return zero. Called by the scheduler. */ +/** \brief Look for the next timeout event time. + + This function looks up when the next genwait_wait() call will timeout. This + function is for the internal use of the scheduler, and should not be called + from user code. + + \return The next timeout time in milliseconds since boot, or + 0 if there are no pending genwait_wait() calls +*/ uint64 genwait_next_timeout(); +/** \cond */ /* Initialize the genwait system */ int genwait_init(); /* Shut down the genwait system */ void genwait_shutdown(); +/** \endcond */ __END_DECLS Modified: kos/include/kos/iovec.h =================================================================== --- kos/include/kos/iovec.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/iovec.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,6 +5,14 @@ */ +/** \file kos/iovec.h + \brief Scatter/Gather arrays. + + This file contains the definition of a scatter/gather array. + + \author Dan Potter +*/ + #ifndef __KOS_IOVEC_H #define __KOS_IOVEC_H @@ -13,9 +21,12 @@ #include <stddef.h> +/** \brief Scatter/Gather array. + \headerfile kos/iovec.h +*/ typedef struct iovec { - char *iov_base; /* Base address */ - size_t iov_len; /* Length */ + char *iov_base; /**< \brief Base address */ + size_t iov_len; /**< \brief Length */ } iovec_t; __END_DECLS Modified: kos/include/kos/limits.h =================================================================== --- kos/include/kos/limits.h 2010-07-20 15:12:49 UTC (rev 673) +++ kos/include/kos/limits.h 2010-07-20 20:05:07 UTC (rev 674) @@ -5,10 +5,18 @@ */ +/** \file kos/limits.h + \brief Limits. + + This file contains definitions of limits of various things. + + \author Dan Potter +*/ + #ifndef __KOS_LIMITS_H #define __KOS_LIMITS_H -#define MAX_FN_LEN 256 /* Max filename length */ -#define PATH_MAX 4095 /* Max path length */ +#define MAX_FN_LEN 256 /**< \brief Max filename length */ +#define PATH_MAX 4095 /**< \brief Max path length */ #endif /* __KOS_LIMITS_H */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-20 15:12:55
|
Revision: 673 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=673&view=rev Author: ljsebald Date: 2010-07-20 15:12:49 +0000 (Tue, 20 Jul 2010) Log Message: ----------- fs_builtin has been gone for a while now, why these remnants are here, I have no idea. Modified Paths: -------------- kos/include/kos.h Removed Paths: ------------- kos/include/kos/fs_builtin.h Deleted: kos/include/kos/fs_builtin.h =================================================================== --- kos/include/kos/fs_builtin.h 2010-07-19 21:20:35 UTC (rev 672) +++ kos/include/kos/fs_builtin.h 2010-07-20 15:12:49 UTC (rev 673) @@ -1,37 +0,0 @@ -/* KallistiOS ##version## - - kos/fs_builtin.h - (c)2000-2001 Dan Potter - -*/ - -#ifndef __KOS_FS_BUILTIN_H -#define __KOS_FS_BUILTIN_H - -/* Definitions for the "built-in" file system */ - -#include <sys/cdefs.h> -__BEGIN_DECLS - -#include <kos/limits.h> -#include <kos/fs.h> - -typedef struct { - char name[MAX_FN_LEN]; /* File's full path name */ - uint8 *data; /* Data for the file */ - uint32 size; /* Data size */ -} fs_builtin_ent; - - -/* Set a table */ -int fs_builtin_set_table(fs_builtin_ent *tbl, int cnt); - -/* Init func */ -int fs_builtin_init(); -int fs_builtin_shutdown(); - -__END_DECLS - -#endif /* __KOS_FS_BUILTIN_H */ - - Modified: kos/include/kos.h =================================================================== --- kos/include/kos.h 2010-07-19 21:20:35 UTC (rev 672) +++ kos/include/kos.h 2010-07-20 15:12:49 UTC (rev 673) @@ -33,7 +33,6 @@ #include <unistd.h> #include <kos/fs.h> -#include <kos/fs_builtin.h> #include <kos/fs_romdisk.h> #include <kos/fs_ramdisk.h> #include <kos/fs_pty.h> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-19 21:20:45
|
Revision: 672 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=672&view=rev Author: ljsebald Date: 2010-07-19 21:20:35 +0000 (Mon, 19 Jul 2010) Log Message: ----------- More Doxygen comments... Modified Paths: -------------- kos/include/kos/dbglog.h kos/kernel/arch/dreamcast/include/dc/fs_dclnative.h kos/kernel/arch/dreamcast/include/dc/fs_dcload.h kos/kernel/arch/dreamcast/include/dc/fs_dclsocket.h kos/kernel/arch/dreamcast/include/dc/fs_iso9660.h kos/kernel/arch/dreamcast/include/dc/fs_vmu.h kos/kernel/arch/dreamcast/include/dc/matrix.h kos/kernel/arch/dreamcast/include/dc/matrix3d.h kos/kernel/arch/dreamcast/include/dc/sq.h kos/kernel/arch/dreamcast/include/dc/vblank.h Modified: kos/include/kos/dbglog.h =================================================================== --- kos/include/kos/dbglog.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/include/kos/dbglog.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,16 @@ */ +/** \file kos/dbglog.h + \brief A debugging log. + + This file contains declarations related a debugging log. This log can be + used to restrict log messages, for instance to make it so that only the most + urgent of messages get printed for a release version of a program. + + \author Dan Potter +*/ + #ifndef __KOS_DBGLOG_H #define __KOS_DBGLOG_H @@ -15,23 +25,44 @@ #include <stdarg.h> #include <kos/fs.h> -/* Kernel debugging printf; all output sent to this is filtered through - a kernel log level check before actually being printed. This way, you - can set the level of debug info you want to see (or want your users - to see). */ +/** \brief Kernel debugging printf. + + This function is similar to printf(), but filters its output through a log + level check before being printed. This way, you can set the level of debug + info you want to see (or want your users to see). + + \param level The level of importance of this message. + \param fmt Message format string. + \param ... Format arguments + \see dbglog_levels +*/ void dbglog(int level, const char *fmt, ...) __printflike(2, 3); -/* Log levels for the above */ -#define DBG_DEAD 0 /* The system is dead */ -#define DBG_CRITICAL 1 /* A critical error message */ -#define DBG_ERROR 2 /* A normal error message */ -#define DBG_WARNING 3 /* Potential problem */ -#define DBG_NOTICE 4 /* Normal but significant */ -#define DBG_INFO 5 /* Informational messages */ -#define DBG_DEBUG 6 /* User debug messages */ -#define DBG_KDEBUG 7 /* Kernel debug messages */ +/** \defgroup dbglog_levels Log levels for dbglog -/* Set debug level */ + This is the list of levels that are allowed to be passed into the dbglog() + function, representing different levels of importance. + + @{ +*/ +#define DBG_DEAD 0 /**< \brief The system is dead */ +#define DBG_CRITICAL 1 /**< \brief A critical error message */ +#define DBG_ERROR 2 /**< \brief A normal error message */ +#define DBG_WARNING 3 /**< \brief Potential problem */ +#define DBG_NOTICE 4 /**< \brief Normal but significant */ +#define DBG_INFO 5 /**< \brief Informational messages */ +#define DBG_DEBUG 6 /**< \brief User debug messages */ +#define DBG_KDEBUG 7 /**< \brief Kernel debug messages */ +/** @} */ + +/** \brief Set the debugging log level. + + This function sets the level for which dbglog() will ignore messages for if + the message has a higher level. + + \param level The level to stop paying attention after. + \see dbglog_levels +*/ void dbglog_set_level(int level); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/fs_dclnative.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fs_dclnative.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/fs_dclnative.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,18 @@ */ +/** \file dc/fs_dclnative.h + \brief Implementation of dcload-ip over KOS network drivers. + + This file contains declarations related to using dcload-ip over the KOS + network adapter drivers. This should be considered deprecated in favor of + fs_dclsocket, and I'm not even sure that it would still work at this point. + + \author Dan Potter + \see dc/fs_dclsocket.h + \see dc/fs_dcload.h +*/ + #ifndef __DC_FS_DCLNATIVE_H #define __DC_FS_DCLNATIVE_H @@ -20,6 +32,7 @@ #include <dc/fs_dcload.h> +/* \cond */ /* Printk replacement */ void dclnative_printk(const char *str); @@ -38,6 +51,8 @@ int fs_dclnative_init(); int fs_dclnative_shutdown(); +/* \endcond */ + __END_DECLS #endif /* __DC_FS_DCLNATIVE_H */ Modified: kos/kernel/arch/dreamcast/include/dc/fs_dcload.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fs_dcload.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/fs_dcload.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,17 @@ */ +/** \file dc/fs_dcload.h + \brief Implementation of dcload "filesystem". + + This file contains declarations related to using dcload, both in its -ip and + -serial forms. This is only used for dcload-ip support if the internal + network stack is not initialized at start via KOS_INIT_FLAGS(). + + \author Andrew Kieschnick + \see dc/fs_dclsocket.h +*/ + #ifndef __DC_FS_DCLOAD_H #define __DC_FS_DCLOAD_H @@ -18,18 +29,26 @@ #include <kos/fs.h> #include <kos/dbgio.h> +/* \cond */ extern dbgio_handler_t dbgio_dcload; +/* \endcond */ /* dcload magic value */ +/** \brief The dcload magic value! */ #define DCLOADMAGICVALUE 0xdeadbeef + +/** \brief The address of the dcload magic value */ #define DCLOADMAGICADDR (unsigned int *)0x8c004004 /* Are we using dc-load-serial or dc-load-ip? */ -#define DCLOAD_TYPE_NONE -1 -#define DCLOAD_TYPE_SER 0 -#define DCLOAD_TYPE_IP 1 +#define DCLOAD_TYPE_NONE -1 /**< \brief No dcload connection */ +#define DCLOAD_TYPE_SER 0 /**< \brief dcload-serial connection */ +#define DCLOAD_TYPE_IP 1 /**< \brief dcload-ip connection */ + +/** \brief What type of dcload connection do we have? */ extern int dcload_type; +/* \cond */ /* Available dcload console commands */ #define DCLOAD_READ 0 @@ -119,6 +138,8 @@ /* Init func for dcload-ip + lwIP */ int fs_dcload_init_lwip(void *p); +/* \endcond */ + __END_DECLS #endif /* __KALLISTI_FS_DCLOAD_H */ Modified: kos/kernel/arch/dreamcast/include/dc/fs_dclsocket.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fs_dclsocket.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/fs_dclsocket.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,17 @@ */ +/** \file dc/fs_dclsocket.h + \brief Implementation of dcload-ip over KOS sockets. + + This file contains declarations related to using dcload-ip over the KOS + sockets system. If dcload-ip support is enabled at the same time as network + support, this is how the communications will happen. There isn't really + anything that users will need to deal with in here. + + \author Lawrence Sebald +*/ + #ifndef __DC_FSDCLSOCKET_H #define __DC_FSDCLSOCKET_H @@ -13,6 +24,7 @@ #include <dc/fs_dcload.h> +/* \cond */ extern dbgio_handler_t dbgio_dcls; /* Initialization */ @@ -20,6 +32,7 @@ int fs_dclsocket_init(); int fs_dclsocket_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/fs_iso9660.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fs_iso9660.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/fs_iso9660.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,23 @@ */ +/** \file dc/fs_iso9660.h + \brief ISO9660 (CD-ROM) filesystem driver. + + This driver implements support for reading files from a CD-ROM or CD-R in + the Dreamcast's disc drive. This filesystem mounts itself on /cd. + + This driver supports Rock Ridge, thanks to Andrew Kieschnick. The driver + also supports the Joliet extensions thanks to Bero. + + The implementation was originally based on a simple ISO9660 implementation + by Marcus Comstedt. + + \author Dan Potter + \author Andrew Kieschnick + \author Bero +*/ + #ifndef __DC_FS_ISO9660_H #define __DC_FS_ISO9660_H @@ -15,15 +32,23 @@ #include <kos/limits.h> #include <kos/fs.h> +/** \brief The maximum number of files that can be open at once. */ #define MAX_ISO_FILES 8 -/* Call to reset the cache and generally assume that a new disc - has been (or will be) inserted. This is equivalent to the old - iso_ioctl() call. */ +/** \brief Reset the internal ISO9660 cache. + + This function resets the cache of the ISO9660 driver, breaking connections + to all files. This generally assumes that a new disc has been or will be + inserted. + + \retval 0 On success. +*/ int iso_reset(); +/* \cond */ int fs_iso9660_init(); int fs_iso9660_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/fs_vmu.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fs_vmu.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/fs_vmu.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,26 @@ */ +/** \file dc/fs_vmu.h + \brief VMU filesystem driver. + + The VMU filesystem driver mounts itself on /vmu of the VFS. Each memory card + has its own subdirectory off of that directory (i.e, /vmu/a1 for slot 1 of + the first controller). VMUs themselves have no subdirectories, so the driver + itself is fairly simple. + + Files on a VMU must be multiples of 512 bytes in size, and should have a + header attached so that they show up in the BIOS menu. + + This layer is built off of the vmufs layer, which does all the low-level + operations. It is generally easier to work with things at this level though, + so that you can use the normal libc file access functions. + + \author Dan Potter + \see dc/vmu_pkg.h + \see dc/vmufs.h +*/ + #ifndef __DC_FS_VMU_H #define __DC_FS_VMU_H @@ -13,9 +33,11 @@ #include <kos/fs.h> +/* \cond */ /* Initialization */ int fs_vmu_init(); int fs_vmu_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/matrix.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/matrix.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/matrix.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,17 @@ */ +/** \file dc/matrix.h + \brief Basic matrix operations. + + This file contains various basic matrix math functionality for using the + SH4's matrix transformation unit. Higher level functionality, like the 3D + functionality is built off of these operations. + + \author Dan Potter + \see dc/matrix3d.h +*/ + #ifndef __DC_MATRIX_H #define __DC_MATRIX_H @@ -13,35 +24,77 @@ #include <kos/vector.h> -/* Copy the internal matrix out to a memory one */ +/** \brief Copy the internal matrix to a memory one. + + This function stores the current internal matrix to one in memory. + + \param out A pointer to where to store the matrix (must be at + least 8-byte aligned, should be 32-byte aligned). +*/ void mat_store(matrix_t *out); -/* Copy a memory matrix into the internal one */ +/** \brief Copy a memory matrix into the internal one. + + This function loads the internal matrix with the values of one in memory. + + \param out A pointer to where to load the matrix from (must be + at least 8-byte aligned, should be 32-byte aligned). +*/ void mat_load(matrix_t *out); -/* Clear internal to an identity matrix */ +/** \brief Clear the internal matrix to identity. + + This function clears the internal matrix to a standard identity matrix. +*/ void mat_identity(); -/* "Apply" a matrix: multiply a matrix onto the "internal" one */ +/** \brief Apply a matrix. + + This function multiplies a matrix in memory onto the internal matrix. + + \param src A poitner to the matrix to multiply. +*/ void mat_apply(matrix_t *src); -/* Transform zero or more sets of vectors using the current internal - matrix. Each vector is three floats long. */ +/** \brief Transform vectors by the internal matrix. + + This function transforms zero or more sets of vectors by the current + internal matrix. Each vector is 3 single-precision floats long. + + \param invecs The list of input vectors. + \param outvecs The list of output vectors. + \param veccnt How many vectors are in the list. + \param vecskip Number of empty bytes between vectors. +*/ void mat_transform(vector_t *invecs, vector_t *outvecs, int veccnt, int vecskip); -/* Transform zero or more sets of vertices using the current internal - matrix, directly to the store queues. Each vertex is 32 bytes long. - All non-xyz data will be copied over along with the transformed - coordinates. Minimum number of vertices: 1. +/** \brief Transform vectors by the internal matrix into the store queues. - Note taht the QACRx registers must have already been set. + This function transforms one or more sets of vertices using the current + internal matrix directly into the store queues. Each vertex is exactly + 32-bytes long, and the non-xyz data that is with it will be copied over with + the transformed coordinates. This is perfect, for instance, for transforming + pvr_vertex_t vertices. - This was contributed by Jim Ursetto. */ + \param input The list of input vertices. + \param output The output pointer. + \param veccnt The number of vertices to transform. + \note The \ref QACR0 and \ref QACR1 registers must be set + appropriately BEFORE calling this function. + \author Jim Ursetto +*/ void mat_transform_sq(void * input, void * output, int veccnt); -/* Inline mat_transform which works on the three coordinates passed in; - this works most efficiently if you've already got the three numbers - (x,y,z) in the right registers (fr0,fr1,fr2). */ +/** \brief Macro to transform a single vertex by the internal matrix. + + This macro is an inline assembly operation to transform a single vertex. It + works most efficiently if the x value is in fr0, y is in fr1, and z is in + fr2 before using the macro. + + \param x The X coordinate to transform. + \param y The Y coordinate to transform. + \param z The Z coordinate to transform. +*/ #define mat_trans_single(x, y, z) { \ register float __x __asm__("fr0") = (x); \ register float __y __asm__("fr1") = (y); \ @@ -59,7 +112,19 @@ x = __x; y = __y; z = __z; \ } -/* Same as above, but allows an input to and preserves the Z/W value */ +/** \brief Macro to transform a single vertex by the internal matrix. + + This macro is an inline assembly operation to transform a single vertex. It + works most efficiently if the x value is in fr0, y is in fr1, z is in + fr2, and w is in fr3 before using the macro. This macro is similar to + mat_trans_single(), but this one allows an input to and preserves the Z/W + value. + + \param x The X coordinate to transform. + \param y The Y coordinate to transform. + \param z The Z coordinate to transform. + \param w The W coordinate to transform. +*/ #define mat_trans_single4(x, y, z, w) { \ register float __x __asm__("fr0") = (x); \ register float __y __asm__("fr1") = (y); \ @@ -79,8 +144,17 @@ x = __x; y = __y; z = __z; w = __w; \ } -/* This is like mat_trans_single, but it leaves z/w instead of 1/w - for the z component. */ +/** \brief Macro to transform a single vertex by the internal matrix. + + This macro is an inline assembly operation to transform a single vertex. It + works most efficiently if the x value is in fr0, y is in fr1, and z is in + fr2 before using the macro. This macro is similar to mat_trans_single(), but + this one leaves z/w instead of 1/w for the z component. + + \param x The X coordinate to transform. + \param y The Y coordinate to transform. + \param z The Z coordinate to transform. +*/ #define mat_trans_single3(x, y, z) { \ register float __x __asm__("fr0") = (x); \ register float __y __asm__("fr1") = (y); \ @@ -97,7 +171,19 @@ x = __x; y = __y; z = __z; \ } -/* Transform vector, without any perspective division. */ +/** \brief Macro to transform a single vertex by the internal matrix with no + perspective division. + + This macro is an inline assembly operation to transform a single vertex. It + works most efficiently if the x value is in fr0, y is in fr1, z is in + fr2, and w is in fr3 before using the macro. This macro is similar to + mat_trans_single(), but this one does not do any perspective division. + + \param x The X coordinate to transform. + \param y The Y coordinate to transform. + \param z The Z coordinate to transform. + \param w The W coordinate to transform. +*/ #define mat_trans_nodiv(x, y, z, w) { \ register float __x __asm__("fr0") = (x); \ register float __y __asm__("fr1") = (y); \ Modified: kos/kernel/arch/dreamcast/include/dc/matrix3d.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/matrix3d.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/matrix3d.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,16 @@ */ +/** \file dc/matrix3d.h + \brief 3D matrix operations. + + This file contains various 3D matrix math functionality for using the SH4's + matrix transformation unit. + + \author Dan Potter + \author Jordan DeLong +*/ + #ifndef __KOS_MATRIX3D_H #define __KOS_MATRIX3D_H @@ -13,23 +23,83 @@ #include <dc/matrix.h> +/** \brief Rotate around the X-axis. + + This function sets up a rotation matrix around the X-axis. + + \param r The angle to rotate, in radians. +*/ void mat_rotate_x(float r); + +/** \brief Rotate around the Y-axis. + + This function sets up a rotation matrix around the Y-axis. + + \param r The angle to rotate, in radians. +*/ void mat_rotate_y(float r); + +/** \brief Rotate around the Z-axis. + + This function sets up a rotation matrix around the Z-axis. + + \param r The angle to rotate, in radians. +*/ void mat_rotate_z(float r); + +/** \brief Rotate around all axes. + + This function sets up a rotation matrix around the X-axis, then around the + Y, then around the Z. + + \param xr The angle to rotate around the X-axis, in radians. + \param yr The angle to rotate around the Y-axis, in radians. + \param zr The angle to rotate around the Z-axis, in radians. +*/ void mat_rotate(float xr, float yr, float zr); + +/** \brief Perform a 3D translation. + + This function sets up a translation matrix with the specified parameters. + + \param x The amount to translate in X. + \param y The amount to translate in Y. + \param z The amount to translate in Z. +*/ void mat_translate(float x, float y, float z); + +/** \brief Perform a 3D scale operation. + + This function sets up a scaling matrix with the specified parameters. + + \param x The ratio to scale in X. + \param y The ratio to scale in Y. + \param z The ratio to scale in Z. +*/ void mat_scale(float x, float y, float z); -/** - This sets up a perspective view frustum for basic 3D usage. The xcenter - and ycenter parameters are dependent on your screen resolution (or however - you want to do it); cot_fovy_2 is 1.0/tan(view_angle/2). Use 1.0 for a - normal 90' view. znear and zfar are what they sound like. */ +/** \brief Set up a perspective view frustum. + + This function sets up a perspective view frustum for basic 3D usage. + + \param xcenter Center of the X direction. + \param ycenter Center of the Y direction. + \param cot_fovy_2 1.0 / tan(view_angle / 2). + \param znear Near Z-plane. + \param zfar Far Z-plane. +*/ void mat_perspective(float xcenter, float ycenter, float cot_fovy_2, float znear, float zfar); -/** - Performs a "camera" function with rotations and translations. */ +/** \brief Set up a "camera". + + This function acts as the similarly named GL function to set up a "camera" + by doing rotations/translations. + + \param eye The eye coordinate. + \param center The center coordinate. + \param up The up vector. +*/ void mat_lookat(const point_t * eye, const point_t * center, const vector_t * up); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/sq.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/sq.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/sq.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,7 +5,17 @@ */ +/** \file dc/sq.h + \brief Functions to access the SH4 Store Queues. + The store queues are a way to do efficient burst transfers from the CPU to + external memory. They can be used in a variety of ways, such as to transfer + a texture to PVR memory. The transfers are in units of 32-bytes, and the + destinations must be 32-byte aligned. + + \author Andrew Kieschnick +*/ + #ifndef __DC_SQ_H #define __DC_SQ_H @@ -14,22 +24,68 @@ #include <arch/types.h> +/** \brief Store Queue 0 access register */ #define QACR0 (*(volatile unsigned int *)(void *)0xff000038) + +/** \brief Store Queue 1 access register */ #define QACR1 (*(volatile unsigned int *)(void *)0xff00003c) -/* clears n bytes at dest, dest must be 32-byte aligned */ +/** \brief Clear a block of memory. + + This function is similar to calling memset() with a value to set of 0, but + uses the store queues to do its work. + + \param dest The address to begin clearing at (32-byte aligned). + \param n The number of bytes to clear (multiple of 32). +*/ void sq_clr(void *dest, int n); -/* copies n bytes from src to dest, dest must be 32-byte aligned */ +/** \brief Copy a block of memory. + + This function is similar to memcpy4(), but uses the store queues to do its + work. + + \param dest The address to copy to (32-byte aligned). + \param src The address to copy from (32-bit (4-byte) aligned). + \param n The number of bytes to copy (multiple of 32). + \return The original value of dest. +*/ void * sq_cpy(void *dest, void *src, int n); -/* fills n bytes at s with byte c, s must be 32-byte aligned */ +/** \brief Set a block of memory to an 8-bit value. + + This function is similar to calling memset(), but uses the store queues to + do its work. + + \param s The address to begin setting at (32-byte aligned). + \param c The value to set (in the low 8-bits). + \param n The number of bytes to set (multiple of 32). + \return The original value of dest. +*/ void * sq_set(void *s, uint32 c, int n); -/* fills n bytes at s with short c, s must be 32-byte aligned */ +/** \brief Set a block of memory to a 16-bit value. + + This function is similar to calling memset2(), but uses the store queues to + do its work. + + \param s The address to begin setting at (32-byte aligned). + \param c The value to set (in the low 16-bits). + \param n The number of bytes to set (multiple of 32). + \return The original value of dest. +*/ void * sq_set16(void *s, uint32 c, int n); -/* fills n bytes at s with int c, s must be 32-byte aligned */ +/** \brief Set a block of memory to a 32-bit value. + + This function is similar to calling memset4(), but uses the store queues to + do its work. + + \param s The address to begin setting at (32-byte aligned). + \param c The value to set (all 32-bits). + \param n The number of bytes to set (multiple of 32). + \return The original value of dest. +*/ void * sq_set32(void *s, uint32 c, int n); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/vblank.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/vblank.h 2010-07-19 18:36:33 UTC (rev 671) +++ kos/kernel/arch/dreamcast/include/dc/vblank.h 2010-07-19 21:20:35 UTC (rev 672) @@ -5,6 +5,16 @@ */ +/** \file dc/vblank.h + \brief VBlank handler registration. + + This file allows functions to be registered to be called on each vblank + interrupt that occurs. This gives a way to schedule small functions that + must occur regularly, without using threads. + + \author Dan Potter +*/ + #ifndef __DC_VBLANK_H #define __DC_VBLANK_H @@ -13,23 +23,37 @@ #include <dc/asic.h> -/** Add a vblank handler. The function will be called at the start of every - vertical blanking period with the same parameters that were passed to - the original ASIC handler. Returns <0 on failure or a handle otherwise. */ +/** \brief Add a vblank handler. + + This function adds a handler to the vblank handler list. The function will + be called at the start of every vblank period with the same parameters that + were passed to the IRQ handler for vblanks. + + \param hnd The handler to add. + \return The handle id on success, or <0 on failure. +*/ int vblank_handler_add(asic_evt_handler hnd); -/** Remove a vblank handler. Pass the handle returned from - vblank_handler_add. */ +/** \brief Remove a vblank handler. + + This function removes the specified handler from the vblank handler list. + + \param handle The handle id to remove (returned by + vblank_handler_add() when the handler was added). + \retval 0 On success. + \retval -1 On failure. +*/ int vblank_handler_remove(int handle); +/* \cond */ /** Initialize the vblank handler. This must be called after the asic module is initialized. */ int vblank_init(); /** Shut down the vblank handler. */ int vblank_shutdown(); +/* \endcond */ - __END_DECLS #endif /* __DC_VBLANK_H */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-19 18:36:39
|
Revision: 671 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=671&view=rev Author: ljsebald Date: 2010-07-19 18:36:33 +0000 (Mon, 19 Jul 2010) Log Message: ----------- Add Doxygen comments to a few more files, and fix a few comments in other ones. Modified Paths: -------------- kos/include/kos/string.h kos/include/sys/socket.h kos/kernel/arch/dreamcast/include/arch/exec.h kos/kernel/arch/dreamcast/include/arch/gdb.h kos/kernel/arch/dreamcast/include/arch/rtc.h kos/kernel/arch/dreamcast/include/arch/stack.h kos/kernel/arch/dreamcast/include/arch/timer.h kos/kernel/arch/dreamcast/include/arch/types.h kos/kernel/arch/dreamcast/include/dc/maple/vmu.h kos/kernel/arch/dreamcast/sound/arm/stream.drv Modified: kos/include/kos/string.h =================================================================== --- kos/include/kos/string.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/include/kos/string.h 2010-07-19 18:36:33 UTC (rev 671) @@ -41,7 +41,7 @@ This implies that all 32-bits of c are used, not just the first 8 as in memset(). - \param dest The destination of the set. + \param s The destination of the set. \param c The value to set to. \param count The number of bytes to set. This should be divisible by 4 (and will be rounded down if not). @@ -67,7 +67,7 @@ This implies that all 16-bits of c are used, not just the first 8 as in memset(). - \param dest The destination of the set. + \param s The destination of the set. \param c The value to set to. \param count The number of bytes to set. This should be divisible by 2 (and will be rounded down if not). Modified: kos/include/sys/socket.h =================================================================== --- kos/include/sys/socket.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/include/sys/socket.h 2010-07-19 18:36:33 UTC (rev 671) @@ -163,7 +163,7 @@ This function sends messages to the peer on a connected socket. \param socket The socket to send on. - \param buffer A pointer to a buffer with the message to send. + \param message A pointer to a buffer with the message to send. \param length The length of the message. \param flags The type of message transmission. Set to 0 for now. \return On success, the number of bytes sent. On error, -1, @@ -178,7 +178,7 @@ peer that the socket is connected to, or it may simply return error. \param socket The socket to send on. - \param buffer A pointer to a buffer with the message to send. + \param message A pointer to a buffer with the message to send. \param length The length of the message. \param flags The type of message transmission. Set to 0 for now. \param dest_addr A pointer to a sockaddr structure with the peer's name. Modified: kos/kernel/arch/dreamcast/include/arch/exec.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/exec.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/exec.h 2010-07-19 18:36:33 UTC (rev 671) @@ -5,15 +5,43 @@ */ +/** \file arch/exec.h + \brief Program execution. + + This file contains functions that allow you to replace the currently running + program with another binary that has already been loaded into memory. Doing + so is expected to replace the currently running binary in its entirety, and + these functions do not return to the calling function. + + \author Dan Potter +*/ + #ifndef __ARCH_EXEC_H #define __ARCH_EXEC_H #include <sys/cdefs.h> __BEGIN_DECLS -/* Replace the currently running image with whatever is at - the pointer; note that this call will never return. */ +/** \brief Replace the currently running binary. + + This function will replace the currently running binary with whatever is + at the specified address. This function does not return. + + \param image The binary to run (already loaded into RAM). + \param length The length of the binary. + \param address The address of the binary's starting point. +*/ void arch_exec_at(const void *image, uint32 length, uint32 address) __noreturn; + +/** \brief Replace the currently running binary at the default address. + + This is a convenience function for arch_exec_at() that assumes that the + binary has been set up with its starting point at the standard location. + In the case of the Dreamcast, this is 0xAC010000 (or 0x8C010000, in P1). + + \param image The binary to run (already loaded into RAM). + \param length The length of the binary. +*/ void arch_exec(const void *image, uint32 length) __noreturn; __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/gdb.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/gdb.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/gdb.h 2010-07-19 18:36:33 UTC (rev 671) @@ -5,16 +5,33 @@ */ +/** \file arch/gdb.h + \brief GNU Debugger support. + + This file contains functions to set up and utilize GDB with KallistiOS. + + \author Dan Potter +*/ + #ifndef __ARCH_GDB_H #define __ARCH_GDB_H #include <sys/cdefs.h> __BEGIN_DECLS -/* Initialize the GDB stub */ +/** \brief Initialize the GDB stub. + + This function initializes GDB support. It should be the first thing you do + in your program, when you wish to use GDB for debugging. +*/ void gdb_init(); -/* Manually raise a GDB breakpoint */ +/** \brief Manually raise a GDB breakpoint. + + This function manually raises a GDB breakpoint at the current location in + the code, allowing you to inspect things with GDB at the point where the + function is called. +*/ void gdb_breakpoint(); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/rtc.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/rtc.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/rtc.h 2010-07-19 18:36:33 UTC (rev 671) @@ -5,6 +5,16 @@ */ +/** \file arch/rtc.h + \brief Low-level real time clock functionality. + + This file contains functions for interacting with the real time clock in the + Dreamcast. Generally, you should prefer interacting with the higher level + standard C functions, like time(), rather than these. + + \author Dan Potter +*/ + #ifndef __ARCH_RTC_H #define __ARCH_RTC_H @@ -13,17 +23,30 @@ #include <time.h> -/* Returns the date/time value as a UNIX epoch time stamp */ +/** \brief Get the current date/time. + + This function retrieves the current RTC value as a standard UNIX timestamp + (with an epoch of January 1, 1970 00:00). This is assumed to be in the + timezone of the user (as the RTC does not support timezones). + + \return The current UNIX-style timestamp (local time). +*/ time_t rtc_unix_secs(); -/* Returns the date/time that the system was booted as a UNIX epoch time - stamp. Adding this to the value from timer_ms_gettime() will - produce a current timestamp. */ +/** \brief Get the time that the sytem was booted. + + This function retrieves the RTC value from when KallistiOS was started. As + with rtc_unix_secs(), this is a UNIX-style timestamp in local time. + + \return The boot time as a UNIX-style timestamp. +*/ time_t rtc_boot_time(); +/* \cond */ /* Init / Shutdown */ int rtc_init(); void rtc_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/stack.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/stack.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/stack.h 2010-07-19 18:36:33 UTC (rev 671) @@ -42,6 +42,7 @@ printing the results to stdout. This could be used for doing something like stack tracing a main thread from inside an IRQ handler. + \param fp The frame pointer to start from. \param n The number of frames to leave off. */ void arch_stk_trace_at(uint32 fp, int n); Modified: kos/kernel/arch/dreamcast/include/arch/timer.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/timer.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/timer.h 2010-07-19 18:36:33 UTC (rev 671) @@ -5,6 +5,18 @@ */ +/** \file arch/timer.h + \brief Low-level timer functionality. + + This file contains functions for interacting with the timer sources on the + SH4. Many of these functions may interfere with thread operation or other + such things, and should thus be used with caution. Basically, the only + functionality that you might use in practice in here in normal programs is + the gettime functions. + + \author Dan Potter +*/ + #ifndef __ARCH_TIMER_H #define __ARCH_TIMER_H @@ -15,75 +27,203 @@ #include <arch/irq.h> /* Timer sources -- we get four on the SH4 */ -#define TMU0 0 /* Off limits during thread operation */ -#define TMU1 1 /* Used for timer_spin_sleep() */ -#define TMU2 2 /* Used for timer_get_ticks() */ -#define WDT 3 /* Not supported yet */ -/* The main timer for the task switcher to use */ +/** \brief SH4 Timer 0. + + This timer is used for thread operation, and thus is off limits if you want + that to work properly. +*/ +#define TMU0 0 + +/** \brief SH4 Timer 1. + + This timer is used for the timer_spin_sleep() function. +*/ +#define TMU1 1 + +/** \brief SH4 Timer 2. + + This timer is used by the various gettime functions in this header. +*/ +#define TMU2 2 + +/** \brief SH4 Watchdog Timer. + + KallistiOS does not currently support using this timer. +*/ +#define WDT 3 + +/** \brief Which timer does the thread system use? */ #define TIMER_ID TMU0 -/* Pre-initialize a timer; set values but don't start it */ +/** \brief Pre-initialize a timer, but do not start it. + + This function sets up a timer for use, but does not start it. + + \param which The timer to set up (i.e, \ref TMU0). + \param speed The number of ticks per second. + \param interrupts Set to 1 to receive interrupts when the timer ticks. + \retval 0 On success. +*/ int timer_prime(int which, uint32 speed, int interrupts); -/* Start a timer -- starts it running (and interrupts if applicable) */ +/** \brief Start a timer. + + This function starts a timer that has been initialized with timer_prime(), + starting raising interrupts if applicable. + + \param which The timer to start (i.e, \ref TMU0). + \retval 0 On success. +*/ int timer_start(int which); -/* Stop a timer -- and disables its interrupt */ +/** \brief Stop a timer. + + This function stops a timer that was started with timer_start(), and as a + result stops interrupts coming in from the timer. + + \param which The timer to stop (i.e, \ref TMU0). + \retval 0 On success. +*/ int timer_stop(int which); -/* Returns the count value of a timer */ +/** \brief Obtain the count of a timer. + + This function simply returns the count of the timer. + + \param which The timer to inspect (i.e, \ref TMU0). + \return The timer's count. +*/ uint32 timer_count(int which); -/* Clears the timer underflow bit and returns what its value was */ +/** \brief Clear the underflow bit of a timer. + + This function clears the underflow bit of a timer if it was set. + + \param which The timer to inspect (i.e, \ref TMU0). + \retval 0 If the underflow bit was clear (prior to calling). + \retval 1 If the underflow bit was set (prior to calling). +*/ int timer_clear(int which); -/* Spin-loop kernel sleep func: uses the secondary timer in the - SH-4 to very accurately delay even when interrupts are disabled */ +/** \brief Spin-loop sleep function. + + This function is meant as a very accurate delay function, even if threading + and interrupts are disabled. It uses \ref TMU1 to sleep. + + \param ms The number of milliseconds to sleep. +*/ void timer_spin_sleep(int ms); -/* Enable timer interrupts (high priority); needs to move - to irq.c sometime. */ +/** \brief Enable high-priority timer interrupts. + + This function enables interrupts on the specified timer. + + \param which The timer to enable interrupts on (i.e, \ref TMU0). +*/ void timer_enable_ints(int which); -/* Disable timer interrupts; needs to move to irq.c sometime. */ +/** \brief Disable timer interrupts. + + This function disables interrupts on the specified timer. + + \param which The timer to disable interrupts on (i.e, \ref TMU0). +*/ void timer_disable_ints(int which); -/* Check whether ints are enabled */ +/** \brief Check whether interrupts are enabled on a timer. + + This function checks whether or not interrupts are enabled on the specified + timer. + + \param which The timer to inspect (i.e, \ref TMU0). + \retval 0 If interrupts are disabled on the timer. + \retval 1 If interrupts are enabled on the timer. +*/ int timer_ints_enabled(int which); -/* Enable the millisecond timer */ +/** \brief Enable the millisecond timer. + + This function enables the timer used for the gettime functions. This is on + by default. These functions use \ref TMU2 to do their work. +*/ void timer_ms_enable(); + +/** \brief Disable the millisecond timer. + + This function disables the timer used for the gettime functions. Generally, + you will not want to do this, unless you have some need to use the timer + \ref TMU2 for something else. +*/ void timer_ms_disable(); -/* Return the number of ticks since KOS was booted */ +/** \brief Get the current uptime of the system. + + This function retrieves the number of seconds and milliseconds since KOS was + started. + + \param secs A pointer to store the number of seconds since boot + into. + \param msecs A pointer to store the number of milliseconds past + a second since boot. + \note To get the total number of milliseconds since boot, + calculate (*secs * 1000) + *msecs, or use the + timer_ms_gettime64() function. +*/ void timer_ms_gettime(uint32 *secs, uint32 *msecs); -/* Does the same as timer_ms_gettime(), but it merges both values - into a single 64-bit millisecond counter. May be more handy - in some situations. */ +/** \brief Get the current uptime of the system (in milliseconds). + + This function retrieves the number of milliseconds since KOS was started. It + is equivalent to calling timer_ms_gettime() and combining the number of + seconds and milliseconds into one 64-bit value. + + \return The number of milliseconds since KOS started. +*/ uint64 timer_ms_gettime64(); -/* Works like timer_ms_gettime64(), but returns microseconds. In theory - this is more precise, but the exact preciseness is undetermined. */ +/** \brief Get the current uptime of the system (in microseconds). + + This function retrieves the number of microseconds since KOS was started. It + should be more precise, in theory, than timer_ms_gettime64(), but the exact + amount of preciseness is undetermined. + + \return The number of microseconds since KOS started. +*/ uint64 timer_us_gettime64(); -/* Set the callback target for the primary timer. Set to NULL - to disable callbacks. Returns the address of the previous - handler. */ +/** \brief Primary timer callback type. */ typedef void (*timer_primary_callback_t)(irq_context_t *); + +/** \brief Set the primary timer callback. + + This function sets the primary timer callback to the specified function + pointer. Generally, you should not do this, as the threading system relies + on the primary timer to work. + + \param callback The new timer callback (set to NULL to disable). + \return The old timer callback. +*/ timer_primary_callback_t timer_primary_set_callback(timer_primary_callback_t callback); -/* Request a wakeup in approximately N milliseconds. You only get one - simultaneous wakeup. Any subsequent calls here will replace any - pending wakeup. */ +/** \brief Request a primary timer wakeup. + + This function will wake the caller (by calling the primary timer callback) + in approximately the number of milliseconds specified. You can only have one + timer wakeup scheduled at a time. Any subsequently scheduled wakeups will + replace any existing one. + + \param millis The number of milliseconds to schedule for. +*/ void timer_primary_wakeup(uint32 millis); +/* \cond */ /* Init function */ int timer_init(); /* Shutdown */ void timer_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/types.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/types.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/arch/types.h 2010-07-19 18:36:33 UTC (rev 671) @@ -5,6 +5,16 @@ */ +/** \file arch/types.h + \brief Common integer types. + + This file contains typedefs for some common/useful integer types. These + types include ones that tell you exactly how long they are, as well as some + BSD-isms. + + \author Dan Potter +*/ + #ifndef __ARCH_TYPES_H #define __ARCH_TYPES_H @@ -14,59 +24,61 @@ #include <stddef.h> /* Generic types */ -typedef unsigned long long uint64; -typedef unsigned long uint32; -typedef unsigned short uint16; -typedef unsigned char uint8; -typedef long long int64; -typedef long int32; -typedef short int16; -typedef char int8; +typedef unsigned long long uint64; /**< \brief 64-bit unsigned integer */ +typedef unsigned long uint32; /**< \brief 32-bit unsigned integer */ +typedef unsigned short uint16; /**< \brief 16-bit unsigned integer */ +typedef unsigned char uint8; /**< \brief 8-bit unsigned integer */ +typedef long long int64; /**< \brief 64-bit signed integer */ +typedef long int32; /**< \brief 32-bit signed integer */ +typedef short int16; /**< \brief 16-bit signed integer */ +typedef char int8; /**< \brief 8-bit signed integer */ /* Volatile types */ -typedef volatile uint64 vuint64; -typedef volatile uint32 vuint32; -typedef volatile uint16 vuint16; -typedef volatile uint8 vuint8; -typedef volatile int64 vint64; -typedef volatile int32 vint32; -typedef volatile int16 vint16; -typedef volatile int8 vint8; +typedef volatile uint64 vuint64; /**< \brief 64-bit volatile unsigned type */ +typedef volatile uint32 vuint32; /**< \brief 32-bit volatile unsigned type */ +typedef volatile uint16 vuint16; /**< \brief 16-bit volatile unsigned type */ +typedef volatile uint8 vuint8; /**< \brief 8-bit volatile unsigned type */ +typedef volatile int64 vint64; /**< \brief 64-bit volatile signed type */ +typedef volatile int32 vint32; /**< \brief 32-bit volatile signed type */ +typedef volatile int16 vint16; /**< \brief 16-bit volatile signed type */ +typedef volatile int8 vint8; /**< \brief 8-bit volatile signed type */ /* Pointer arithmetic types */ -typedef uint32 ptr_t; +typedef uint32 ptr_t; /**< \brief Pointer arithmetic type */ /* another format for type names */ #ifndef _BSDTYPES_DEFINED + +/* \cond */ #define __u_char_defined #define __u_short_defined #define __u_int_defined #define __u_long_defined #define __ushort_defined #define __uint_defined -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; -typedef unsigned short ushort; -typedef unsigned int uint; +/* \endcond */ + +typedef unsigned char u_char; /**< \brief BSD-style unsigned char */ +typedef unsigned short u_short; /**< \brief BSD-style unsigned short */ +typedef unsigned int u_int; /**< \brief BSD-style unsigned integer */ +typedef unsigned long u_long; /**< \brief BSD-style unsigned long */ +typedef unsigned short ushort; /**< \brief BSD-style unsigned short */ +typedef unsigned int uint; /**< \brief BSD-style unsigned integer */ + +/* \cond */ #define _BSDTYPES_DEFINED +/* \endcond */ + #endif /* _BSDTYPES_DEFINED */ -#if 0 -/* File-specific types */ -typedef size_t ssize_t; -typedef size_t off_t; -#endif - /* This type may be used for any generic handle type that is allowed to be negative (for errors) and has no specific bit count restraints. */ -typedef int handle_t; +typedef int handle_t; /**< \brief Generic "handle" type */ /* Thread and priority types */ -typedef handle_t tid_t; -typedef handle_t prio_t; +typedef handle_t tid_t; /**< \brief Thread ID type */ +typedef handle_t prio_t; /**< \brief Priority value type */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/maple/vmu.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/vmu.h 2010-07-19 15:28:20 UTC (rev 670) +++ kos/kernel/arch/dreamcast/include/dc/maple/vmu.h 2010-07-19 18:36:33 UTC (rev 671) @@ -46,7 +46,7 @@ bitmap is 1bpp, and is 48x32 in size. \param dev The device to draw to. - \param beep The bitmap to show. + \param bitmap The bitmap to show. \retval MAPLE_EOK On success. \retval MAPLE_EAGAIN If the command couldn't be sent. Try again later. \retval MAPLE_ETIMEOUT If the command timed out while blocking. Modified: kos/kernel/arch/dreamcast/sound/arm/stream.drv =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-19 15:28:27
|
Revision: 670 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=670&view=rev Author: ljsebald Date: 2010-07-19 15:28:20 +0000 (Mon, 19 Jul 2010) Log Message: ----------- Add Doxygen comments to a bunch of things, and clean the ones in assert.h up a little bit. Modified Paths: -------------- kos/include/assert.h kos/include/kos/string.h kos/include/kos.h kos/kernel/arch/dreamcast/include/arch/cache.h kos/kernel/arch/dreamcast/include/arch/spinlock.h kos/kernel/arch/dreamcast/include/arch/stack.h kos/kernel/arch/dreamcast/include/dc/fb_console.h Modified: kos/include/assert.h =================================================================== --- kos/include/assert.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/include/assert.h 2010-07-19 15:28:20 UTC (rev 670) @@ -12,8 +12,8 @@ __BEGIN_DECLS /** - \file assert.h - \brief Standard C Assertions + \file assert.h + \brief Standard C Assertions This file contains the standard C assertions to raise an assertion or to change the assertion handler. @@ -31,57 +31,62 @@ # define assert(e) ((void)0) # define assert_msg(e, m) ((void)0) #else -/** - \brief standard C assertion - \param e a value or expression to be evaluated as true or false +/** \brief Standard C assertion macro. - \return if e is true (void)0 is returned, otherwise, the function does not - return and abort() is called + This macro does a standard C assertion, wherein the expression is evaluated, + and if false, the program is ultimately aborted using abort(). If the + expression evaluates to true, the macro does nothing (other than any side + effects of evaluating the expression). + + \param e A value or expression to be evaluated as true or + false. */ # define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, NULL, __FUNCTION__)) -/** - \brief assert with a custom message +/** \brief assert() with a custom message. - \param e a value or expression to be evaluated as true or false - \param m a const char * message + This macro acts the same as the assert() macro, but allows you to specify a + custom message to be printed out if the assertion fails. - \return if e is true (void)0 is returned, otherwise the function does not - return, a custom message is displayed, and abort() is called + \param e A value or expression to be evaluated as true or + false. + \param m A message (const char *). */ # define assert_msg(e, m) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e, m, __FUNCTION__)) #endif +/* \cond */ /* Defined in assert.c */ void __assert(const char *file, int line, const char *expr, const char *msg, const char *func); +/* \endcond */ -/** - \brief assert handler +/** \brief Assertion handler type. - An assertion handler can be a user defined assertion handler, - otherwise the default is used, which calls abort() + The user can provide their own assertion handler with this type. If none is + provided, a default is used which ultimately prints out the location of the + failed assertion and calls abort(). - \param file The filename where the assertion happened - \param line The line number where the assertion happened - \param expr The expression that raised the assertion - \param msg A custom message for why the assertion happened - \param func The function name from which the assertion happened + \param file The filename where the assertion happened. + \param line The line number where the assertion happened. + \param expr The expression that raised the assertion. + \param msg A custom message for why the assertion happened. + \param func The function name from which the assertion happened. - \sa assert_set_handler + \see assert_set_handler */ typedef void (*assert_handler_t)(const char * file, int line, const char * expr, const char * msg, const char * func); -/** - \brief set an "assert handler" to call on an assert +/** \brief Set an assertion handler to call on a failed assertion. - By default, this will print a message and call abort(). + The default assertion handler simply will print a message and call abort(). - \return the old assert_handler_t address + \return The old assertion handler so it may be restored + later if appropriate. - \sa assert_handler_t + \see assert_handler_t */ assert_handler_t assert_set_handler(assert_handler_t hnd); Modified: kos/include/kos/string.h =================================================================== --- kos/include/kos/string.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/include/kos/string.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,16 @@ */ +/** \file kos/string.h + \brief Variants on standard block memory copy/set functions. + + This file contains variants on the standard block memory copy/set functions. + These variants copy/set memory in the specified block sizes, which may be + helpful for interacting with memory-mapped hardware. + + \author Dan Potter +*/ + #ifndef __KOS_STRING_H #define __KOS_STRING_H @@ -13,9 +23,56 @@ #include <string.h> +/** \brief Copy a block of memory, 4 bytes at a time. + + This function is identical to memcpy(), except it copies 4 bytes at a time. + + \param dest The destination of the copy. + \param src The source to copy. + \param count The number of bytes to copy. This should be + divisible by 4 (and will be rounded down if not). + \return The original value of dest. +*/ void * memcpy4(void * dest,const void *src,size_t count); + +/** \brief Set a block of memory, 4 bytes at a time. + + This function is identical to memset(), except it sets 4 bytes at a time. + This implies that all 32-bits of c are used, not just the first 8 as in + memset(). + + \param dest The destination of the set. + \param c The value to set to. + \param count The number of bytes to set. This should be + divisible by 4 (and will be rounded down if not). + \return The original value of dest. +*/ void * memset4(void * s,unsigned long c,size_t count); + +/** \brief Copy a block of memory, 2 bytes at a time. + + This function is identical to memcpy(), except it copies 2 bytes at a time. + + \param dest The destination of the copy. + \param src The source to copy. + \param count The number of bytes to copy. This should be + divisible by 2 (and will be rounded down if not). + \return The original value of dest. +*/ void * memcpy2(void * dest,const void *src,size_t count); + +/** \brief Set a block of memory, 2 bytes at a time. + + This function is identical to memset(), except it sets 2 bytes at a time. + This implies that all 16-bits of c are used, not just the first 8 as in + memset(). + + \param dest The destination of the set. + \param c The value to set to. + \param count The number of bytes to set. This should be + divisible by 2 (and will be rounded down if not). + \return The original value of dest. +*/ void * memset2(void * s,unsigned short c,size_t count); __END_DECLS Modified: kos/include/kos.h =================================================================== --- kos/include/kos.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/include/kos.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,18 @@ */ +/** \file kos.h + \brief Include everything KOS has to offer! + + This file includes pretty much every KOS-related header file, so you don't + have to figure out what you actually need. The ultimate for the truly lazy! + + You may want to include individual header files yourself if you need more + fine-grained control, as may be more appropriate for some projects. + + \author Dan Potter +*/ + #ifndef __KOS_H #define __KOS_H Modified: kos/kernel/arch/dreamcast/include/arch/cache.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/cache.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/kernel/arch/dreamcast/include/arch/cache.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,15 @@ */ +/** \file arch/cache.h + \brief Cache management functionality. + + This file contains definitions for functions that manage the cache in the + Dreamcast, including functions to flush and invalidate the caches. + + \author Dan Potter +*/ + #ifndef __ARCH_CACHE_H #define __ARCH_CACHE_H @@ -13,13 +22,37 @@ #include <arch/types.h> -/* Flush a range of i-cache, given a physical address range */ +/** \brief Flush the instruction cache. + + This function flushes a range of the instruction cache. + + \param start The physical address to begin flushing at. + \param count The number of bytes to flush. +*/ void icache_flush_range(uint32 start, uint32 count); -/* Invalidate a range of o-cache/d-cache, given a physical address range */ +/** \brief Invalidate the data/operand cache. + + This function invalidates a range of the data/operand cache. If you care + about the contents of the cache that have not been written back yet, use + dcache_flush_range() before using this function. + + \param start The physical address to begin invalidating at. + \param count The number of bytes to invalidate. +*/ void dcache_inval_range(uint32 start, uint32 count); -/* Flush a range of o-cache/d-cache, given a physical address range */ +/** \brief Flush the data/operand cache. + + This function flushes a range of the data/operand cache, forcing a write- + back on all of the data in the specified range. This does not invalidate the + cache in the process (meaning the blocks will still be in the cache, just + not marked as dirty after this has completed). If you wish to invalidate the + cache as well, call dcache_inval_range() after calling this function. + + \param start The physical address to begin flushing at. + \param count The number of bytes to flush. +*/ void dcache_flush_range(uint32 start, uint32 count); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/spinlock.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/spinlock.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/kernel/arch/dreamcast/include/arch/spinlock.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,22 @@ */ +/** \file arch/spinlock.h + \brief Simple locking. + + This file contains definitions for very simple locks. Most of the time, you + will probably not use such low-level locking, but will opt for something + more fully featured like mutexes, semaphores, reader-writer semaphores, or + recursive locks. + + \author Dan Potter + + \see kos/sem.h + \see kos/mutex.h + \see kos/rwsem.h + \see kos/recursive_lock.h +*/ + #ifndef __ARCH_SPINLOCK_H #define __ARCH_SPINLOCK_H @@ -16,19 +32,35 @@ /* DC implementation uses threads most of the time */ #include <kos/thread.h> -/* Spinlock data type */ +/** \brief Spinlock data type. */ typedef volatile int spinlock_t; -/* Value initializer */ +/** \brief Spinlock initializer. + + All created spinlocks should be initialized with this initializer so that + they are in a sane state, ready to be used. +*/ #define SPINLOCK_INITIALIZER 0 -/* Initialize a spinlock */ +/** \brief Initialize a spinlock. + + This function-like macro abstracts initializing a spinlock, in case the + initializer is not applicable to what you are doing. + + \param A A pointer to the spinlock to be initialized. +*/ #define spinlock_init(A) *(A) = SPINLOCK_INITIALIZER /* Note here that even if threads aren't enabled, we'll still set the lock so that it can be used for anti-IRQ protection (e.g., malloc) */ -/* Spin on a lock */ +/** \brief Spin on a lock. + + This macro will spin on the lock, and will not return until the lock has + been obtained for the calling thread. + + \param A A pointer to the spinlock to be locked. +*/ #define spinlock_lock(A) do { \ spinlock_t * __lock = A; \ int __gotlock = 0; \ @@ -42,12 +74,25 @@ } \ } while (0) -/* Free a lock */ +/** \brief Free a lock. + + This macro will unlock the lock that is currently held by the calling + thread. Do not use this macro unless you actually hold the lock! + + \param A A pointer to the spinlock to be unlocked. +*/ #define spinlock_unlock(A) do { \ *(A) = 0; \ } while (0) -/* Determine if a lock is locked */ +/** \brief Determine if a lock is locked. + + This macro will return whether or not the lock specified is actually locked + when it is called. This is NOT a thread-safe way of determining if a lock + will be locked when you get around to locking it! + + \param A A pointer to the spinlock to be checked. +*/ #define spinlock_is_locked(A) ( *(A) != 0 ) __END_DECLS Modified: kos/kernel/arch/dreamcast/include/arch/stack.h =================================================================== --- kos/kernel/arch/dreamcast/include/arch/stack.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/kernel/arch/dreamcast/include/arch/stack.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,17 @@ */ +/** \file arch/stack.h + \brief Stack traces. + + The functions in this file deal with doing stack traces. These functions + will do a stack trace, as specified, printing it out to stdout (usually a + dcload terminal). These functions only work if frame pointers have been + enabled at compile time (-DFRAME_POINTERS and no -fomit-frame-pointer flag). + + \author Dan Potter +*/ + #ifndef __ARCH_STACK_H #define __ARCH_STACK_H @@ -13,12 +24,26 @@ #include <arch/types.h> -/* Do a stack trace from the current function; leave off the first n frames - (i.e., in assert()). */ +/** \brief Do a stack trace from the current function. + + This function does a stack trace from the current function, printing the + results to stdout. This is used, for instance, when an assertion fails in + assert(). + + \param n The number of frames to leave off. Each frame is a + jump to subroutine or branch to subroutine. assert() + leaves off 2 frames, for reference. +*/ void arch_stk_trace(int n); -/* Do a stack trace from the given frame pointer (useful for things like - tracing from an ISR); leave off the first n frames. */ +/** \brief Do a stack trace from the current function. + + This function does a stack trace from the the specified frame pointer, + printing the results to stdout. This could be used for doing something like + stack tracing a main thread from inside an IRQ handler. + + \param n The number of frames to leave off. +*/ void arch_stk_trace_at(uint32 fp, int n); __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/fb_console.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/fb_console.h 2010-07-18 18:03:08 UTC (rev 669) +++ kos/kernel/arch/dreamcast/include/dc/fb_console.h 2010-07-19 15:28:20 UTC (rev 670) @@ -5,6 +5,21 @@ */ +/** \file dc/fb_console.h + \brief A simple dbgio interface to draw to the framebuffer. + + This file contains definitions to interact with a simple framebuffer dbgio + interface. This interface can be moved around in memory and can have its + width and height set so that you can truly customize it to the environment + as needed. This utilizes the bios font functionality to actually draw any + characters. + + To actually use the framebuffer device, pass "fb" as the parameter to + dbgio_dev_select(). + + \author Lawrence Sebald +*/ + #ifndef __DC_FB_CONSOLE_H #define __DC_FB_CONSOLE_H @@ -13,15 +28,29 @@ #include <kos/dbgio.h> +/* \cond */ extern dbgio_handler_t dbgio_fb; +/* \endcond */ -/* Set up the target for the "framebuffer". This allows you to move it around - so that, for example, you could have it render to a texture rather than - to the full framebuffer. If you don't call this, then by default this - dbgio interface prints to the full 640x480 framebuffer with a 32-pixel - border. To restore this functionality after changing it, call this function - with a NULL for t, and the appropriate parameters in w, h, borderx, and - bordery. */ +/** \brief Set the target for the framebuffer dbgio device. + + This function allows you to set a target for the dbgio device on the + framebuffer. This allows you to do things like setting it to render to a + texture rather than to the whole framebuffer, for instance. + + The default setup for the framebuffer dbgio device is to print to the full + 640x480 framebuffer (minus a 32-pixel border around the outside). If you + change this, you can restore the original functionality by passing NULL for + t, 640 for w, 480 for h, and 32 for borderx and bordery. + + \param t The target in memory to render to. + \param w The width of the target. + \param h The height of the target. + \param borderx How much border to leave around the target in the + X direction. + \param bordery How much border to leave around the target in the + Y direction. +*/ void dbgio_fb_set_target(uint16 *t, int w, int h, int borderx, int bordery); __END_DECLS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-18 18:03:14
|
Revision: 669 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=669&view=rev Author: ljsebald Date: 2010-07-18 18:03:08 +0000 (Sun, 18 Jul 2010) Log Message: ----------- Adding Doxygen comments to the rest of the maple device drivers. Modified Paths: -------------- kos/kernel/arch/dreamcast/include/dc/maple/controller.h kos/kernel/arch/dreamcast/include/dc/maple/dreameye.h kos/kernel/arch/dreamcast/include/dc/maple/keyboard.h kos/kernel/arch/dreamcast/include/dc/maple/mouse.h kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h kos/kernel/arch/dreamcast/include/dc/maple/sip.h kos/kernel/arch/dreamcast/include/dc/maple/vmu.h Modified: kos/kernel/arch/dreamcast/include/dc/maple/controller.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/controller.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/controller.h 2010-07-18 18:03:08 UTC (rev 669) @@ -6,6 +6,17 @@ Thanks to Marcus Comstedt for information on the controller. */ +/** \file dc/maple/controller.h + \brief Definitions for using the controller device. + + This file contains the definitions needed to access the Maple controller + device. Obviously, this corresponds to the MAPLE_FUNC_CONTROLLER function + code. + + \author Jordan DeLong + \author Dan Potter +*/ + #ifndef __DC_MAPLE_CONTROLLER_H #define __DC_MAPLE_CONTROLLER_H @@ -14,7 +25,13 @@ #include <arch/types.h> -/* Buttons bitfield defines */ +/** \defgroup controller_buttons Controller button codes + + This is the set of all buttons that are valid for a maple bus controller + device. The names should make it obvious what the button is. + + @{ +*/ #define CONT_C (1<<0) #define CONT_B (1<<1) #define CONT_A (1<<2) @@ -31,6 +48,7 @@ #define CONT_DPAD2_DOWN (1<<13) #define CONT_DPAD2_LEFT (1<<14) #define CONT_DPAD2_RIGHT (1<<15) +/* @} */ /* Raw controller condition structure */ typedef struct { @@ -55,27 +73,79 @@ Note also that this is the struct you will get back if you call maple_dev_status(), NOT a cont_cond_t. However, cont_get_cond() will return the old compatible struct for now. */ + +/** \brief Controller status structure. + + This structure contains information about the status of the controller + device and can be fetched with maple_dev_status(). + + A 1 bit in the buttons bitfield indicates that a button is pressed, and the + joyx, joyy, joy2x, joy2 values are all 0 based (0 is centered). + + \headerfile dc/maple/controller.h +*/ typedef struct { - uint32 buttons; /* Buttons bitfield */ - int ltrig, rtrig; /* Triggers */ - int joyx, joyy; /* Joystick X/Y */ - int joy2x, joy2y; /* Second Joystick X/Y (if applicable) */ + /** \brief Buttons bitfield. + \see controller_buttons + */ + uint32 buttons; + + /** \brief Left trigger value. */ + int ltrig; + + /** \brief Right trigger value. */ + int rtrig; + + /** \brief Main joystick x-axis value. */ + int joyx; + + /** \brief Main joystick y-axis value. */ + int joyy; + + /** \brief Secondary joystick x-axis value (if applicable). */ + int joy2x; + + /** \brief Secondary joystick y-axis value (if applicable). */ + int joy2y; } cont_state_t; +/* \cond */ /* Init / Shutdown */ int cont_init(); void cont_shutdown(); +/* \endcond */ /* Compat function */ int cont_get_cond(uint8 addr, cont_cond_t *cond) __attribute__((deprecated)); -/* Set a controller callback for a button combo; set addr=0 for any controller */ +/** \brief Controller automatic callback type. + + Functions of this type can be set with cont_btn_callback() to respond + automatically to the specified set of buttons being pressed. This can be + used, for instance, to implement the standard A+B+X+Y+Start method of ending + the program running. +*/ typedef void (*cont_btn_callback_t)(uint8 addr, uint32 btns); + +/** \brief Set an automatic button press callback. + + This function sets a callback function to be called when the specified + controller has the set of buttons given pressed. + + \param addr The controller to listen on. This value can be + obtained by using maple_addr(). + \param btns The buttons bitmask to match. + \param cb The callback to call when the buttons are pressed. +*/ void cont_btn_callback(uint8 addr, uint32 btns, cont_btn_callback_t cb); -/* Capability bits - These will be set in the function_data for the controller - in the reply to the devinfo command if the controller supports the - corresponding feature. */ +/** \defgroup controller_caps Controller capability bits. + + These bits will be set in the function_data for the controller's deviceinfo + if the controller supports the corresponding feature. + + @{ +*/ #define CONT_CAPABILITY_C (1<<0) #define CONT_CAPABILITY_B (1<<1) #define CONT_CAPABILITY_A (1<<2) @@ -98,6 +168,7 @@ #define CONT_CAPABILITY_ANALOG_Y (1<<19) #define CONT_CAPABILITY_ANALOG2_X (1<<20) #define CONT_CAPABILITY_ANALOG2_Y (1<<21) +/** @} */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/maple/dreameye.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/dreameye.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/dreameye.h 2010-07-18 18:03:08 UTC (rev 669) @@ -6,7 +6,7 @@ */ /** \file dc/maple/dreameye.h - \brief Definitions using the Dreameye Camera device. + \brief Definitions for using the Dreameye Camera device. This file contains the definitions needed to access the Maple Camera type device (aka, the Dreameye). Currently, this driver allows you to download Modified: kos/kernel/arch/dreamcast/include/dc/maple/keyboard.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/keyboard.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/keyboard.h 2010-07-18 18:03:08 UTC (rev 669) @@ -5,6 +5,17 @@ */ +/** \file dc/maple/keyboard.h + \brief Definitions for using the keyboard device. + + This file contains the definitions needed to access the Maple keyboard + device. Obviously, this corresponds to the MAPLE_FUNC_KEYBOARD function + code. + + \author Jordan DeLong + \author Dan Potter +*/ + #ifndef __DC_MAPLE_KEYBOARD_H #define __DC_MAPLE_KEYBOARD_H @@ -13,7 +24,12 @@ #include <arch/types.h> -/* modifier keys */ +/** \defgroup kbd_mods Keyboard modifier keys + + These are the various modifiers that can be pressed on the keyboard, and are + reflected in the modifiers field of kbd_cond_t. + @{ +*/ #define KBD_MOD_LCTRL (1<<0) #define KBD_MOD_LSHIFT (1<<1) #define KBD_MOD_LALT (1<<2) @@ -22,13 +38,28 @@ #define KBD_MOD_RSHIFT (1<<5) #define KBD_MOD_RALT (1<<6) #define KBD_MOD_S2 (1<<7) +/** @} */ -/* bits for leds : this is not comprensive (need for japanese kbds also) */ +/** \defgroup kbd_leds Keyboard LEDs + + This is the LEDs that can be turned on and off on the keyboard. This list + may not be exhaustive. Think of these sorta like an extension of the + modifiers list. + + @{ +*/ #define KBD_LED_NUMLOCK (1<<0) #define KBD_LED_CAPSLOCK (1<<1) #define KBD_LED_SCRLOCK (1<<2) +/** @} */ -/* defines for the keys (argh...) */ +/** \defgroup kbd_keys Keyboard keys + + This is the list of keys that are on the keyboard that may be pressed. The + keyboard returns keys in this format. + + @{ +*/ #define KBD_KEY_NONE 0x00 #define KBD_KEY_ERROR 0x01 #define KBD_KEY_A 0x04 @@ -127,44 +158,78 @@ #define KBD_KEY_PAD_0 0x62 #define KBD_KEY_PAD_PERIOD 0x63 #define KBD_KEY_S3 0x65 +/** @} */ /* Raw condition structure */ +/** \brief Keyboard raw condition structure. + + This structure is what the keyboard responds with as its current status. + + \headerfile dc/maple/keyboard.h +*/ typedef struct { - uint8 modifiers; /* bitmask of shift keys/etc */ - uint8 leds; /* bitmask of leds that are lit */ - uint8 keys[6]; /* codes for up to 6 currently pressed keys */ + uint8 modifiers; /**< \brief Bitmask of set modifiers. */ + uint8 leds; /**< \brief Bitmask of set LEDs */ + uint8 keys[6]; /**< \brief Key codes for currently pressed keys. */ } kbd_cond_t; /* This is the structure of the 'state' space. This is what you will get back if you call maple_dev_state(). */ +/** \brief Keyboard status structure. + + This structure holds information about the current status of the keyboard + device. This is what maple_dev_status() will return. + + \headerfile dc/maple/keyboard.h +*/ typedef struct kbd_state { - /* The latest raw keyboard condition */ - kbd_cond_t cond; - - /* The key matrix array -- this is an array that lists the status of all - keys on the keyboard. This is mainly used for key repeat and debouncing. */ - uint8 matrix[256]; + /** \brief The lastest raw condition of the keyboard. */ + kbd_cond_t cond; - /* Shift key status */ - int shift_keys; + /** \brief Key array. + + This array lists the state of all possible keys on the keyboard. It can + be used for key repeat and debouncing. + */ + uint8 matrix[256]; + + /** \brief Modifier key status. */ + int shift_keys; } kbd_state_t; -/* Turn keyboard queueing on or off. This is mainly useful if you want - to use the keys for a game where individual keypresses don't mean - as much as having the keys up or down. Setting this state to - a new value will clear the queue. */ +/** \brief Activate or deactivate key queueing. + + This function will turn the internal keyboard queueing on or off. Note that + there is only one queue for the whole system, no matter how many keyboards + are attached, and the queue is of fairly limited length. Turning queueing + off is useful (for instance) in a game where individual keypresses don't + mean as much as having the keys up or down does. + + You can clear the queue (without popping all the keys off) by setting the + active value to a different value than it was. + + The queue is by default on, unless you turn it off. + + \param active Set to non-zero to activate the queue. +*/ void kbd_set_queue(int active); -/* Take a key scancode, encode it appropriate, and place it on the - keyboard queue. At the moment we assume no key overflows. */ -/* int kbd_enqueue(uint8 keycode); */ +/** \brief Pop a key off the keyboard queue. -/* Take a key off the key queue, or return -1 if there is none waiting */ + This function pops the front off of the keyboard queue, and returns the + value to the caller. The value returned will be the ASCII value of the key + pressed (accounting for the shift keys being pressed). + + \return The value at the front of the queue, or -1 if there + are no keys in the queue or queueing is off. +*/ int kbd_get_key(); +/* \cond */ /* Init / Shutdown */ int kbd_init(); void kbd_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/maple/mouse.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/mouse.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/mouse.h 2010-07-18 18:03:08 UTC (rev 669) @@ -5,6 +5,16 @@ */ +/** \file dc/maple/mouse.h + \brief Definitions for using the mouse device. + + This file contains the definitions needed to access the Maple mouse type + device. + + \author Jordan DeLong + \author Dan Potter +*/ + #ifndef __DC_MAPLE_MOUSE_H #define __DC_MAPLE_MOUSE_H @@ -13,11 +23,18 @@ #include <arch/types.h> -/* mouse defines */ -#define MOUSE_RIGHTBUTTON (1<<1) -#define MOUSE_LEFTBUTTON (1<<2) -#define MOUSE_SIDEBUTTON (1<<3) +/** \defgroup mouse_buttons Mouse button codes + These are the possible buttons to press on a maple bus mouse. + + @{ +*/ +#define MOUSE_RIGHTBUTTON (1<<1) /**< \brief Right mouse button */ +#define MOUSE_LEFTBUTTON (1<<2) /**< \brief Left mouse button */ +#define MOUSE_SIDEBUTTON (1<<3) /**< \brief Side mouse button */ +/** @} */ + +/** \brief Mouse center value in the raw condition structure. */ #define MOUSE_DELTA_CENTER 0x200 /* Raw mouse condition structure */ @@ -41,17 +58,38 @@ Note that this is what maple_dev_status() will return. */ + +/** \brief Mouse status structure. + + This structure contains information about the status of the mouse device, + and can be fetched with maple_dev_status(). + + \headerfile dc/maple/mouse.h +*/ typedef struct { - uint32 buttons; - int dx, dy, dz; + /** \brief Buttons pressed bitmask. + \see mouse_buttons + */ + uint32 buttons; + + /** \brief X movement value */ + int dx; + + /** \brief Y movement value */ + int dy; + + /** \brief Z movement value */ + int dz; } mouse_state_t; /* Old maple interface */ int mouse_get_cond(uint8 addr, mouse_cond_t *cond) __attribute__((deprecated)); +/* \cond */ /* Init / Shutdown */ int mouse_init(); void mouse_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h 2010-07-18 18:03:08 UTC (rev 669) @@ -7,7 +7,7 @@ */ /** \file dc/maple/purupuru.h - \brief Definitions using the Puru Puru (Jump) Pack. + \brief Definitions for using the Puru Puru (Jump) Pack. This file contains the definitions needed to access maple jump pack devices. Puru Puru was Sega's internal name for the device, hence why its referred to Modified: kos/kernel/arch/dreamcast/include/dc/maple/sip.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/sip.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/sip.h 2010-07-18 18:03:08 UTC (rev 669) @@ -6,7 +6,7 @@ */ /** \file dc/maple/sip.h - \brief Definitions using the Sound Input Peripheral. + \brief Definitions for using the Sound Input Peripheral. This file contains the definitions needed to access the Maple microphone type device (the Seaman mic). Many thanks go out to ZeZu who pointed me Modified: kos/kernel/arch/dreamcast/include/dc/maple/vmu.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/vmu.h 2010-07-18 16:06:42 UTC (rev 668) +++ kos/kernel/arch/dreamcast/include/dc/maple/vmu.h 2010-07-18 18:03:08 UTC (rev 669) @@ -6,6 +6,18 @@ */ +/** \file dc/maple/vmu.h + \brief Definitions for using the VMU device. + + This file contains the definitions needed to access the Maple VMU device. + This includes all of the functionality of memory cards, including the + MAPLE_FUNC_MEMCARD, MAPLE_FUNC_LCD, and MAPLE_FUNC_CLOCK function codes. + + \author Jordan DeLong + \author Dan Potter + \author Donald Haase +*/ + #ifndef __DC_MAPLE_VMU_H #define __DC_MAPLE_VMU_H @@ -14,18 +26,75 @@ #include <arch/types.h> +/** \brief Make a VMU beep. + + This function sends a raw beep to a VMU, causing the speaker to emit a tone + noise. See http://dcemulation.org/phpBB/viewtopic.php?f=29&t=97048 for the + original information about beeping. + + \param dev The device to attempt to beep. + \param beep The tone to generate. Actual parameters unknown. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent. Try again later. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int vmu_beep_raw(maple_device_t * dev, uint32 beep); + +/** \brief Display a 1bpp bitmap on a VMU screen. + + This function sends a raw bitmap to a VMU to display on its screen. This + bitmap is 1bpp, and is 48x32 in size. + + \param dev The device to draw to. + \param beep The bitmap to show. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent. Try again later. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int vmu_draw_lcd(maple_device_t * dev, void *bitmap); + +/** \brief Read a block from a memory card. + + This function reads a raw block from a memory card. You most likely will not + ever use this directly, but rather will probably use the fs_vmu stuff. + + \param dev The device to read from. + \param blocknum The block number to read. + \param buffer The buffer to read into (512 bytes). + \retval MAPLE_EOK On success. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. + \retval MAPLE_EFAIL On errors other than timeout. +*/ int vmu_block_read(maple_device_t * dev, uint16 blocknum, uint8 *buffer); + +/** \brief Write a block to a memory card. + + This function writes a raw block to a memory card. You most likely will not + ever use this directly, but rather will probably use the fs_vmu stuff. + + \param dev The device to write to. + \param blocknum The block number to write. + \param buffer The buffer to write from (512 bytes). + \retval MAPLE_EOK On success. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. + \retval MAPLE_EFAIL On errors other than timeout. +*/ int vmu_block_write(maple_device_t * dev, uint16 blocknum, uint8 *buffer); -/* Utility function which sets the icon on all available VMUs - from an Xwindows XBM. Imported from libdcutils. */ +/** \brief Set a Xwindows XBM on all VMUs. + + This function takes in a Xwindows XBM and sets the image on all VMUs. This + is a convenience function for vmu_draw_lcd() to broadcast across all VMUs. + + \param vmu_icon The icon to set. +*/ void vmu_set_icon(const char *vmu_icon); +/* \cond */ /* Init / Shutdown */ int vmu_init(); void vmu_shutdown(); +/* \endcond */ __END_DECLS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ljs...@us...> - 2010-07-18 16:06:49
|
Revision: 668 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=668&view=rev Author: ljsebald Date: 2010-07-18 16:06:42 +0000 (Sun, 18 Jul 2010) Log Message: ----------- Add Doxygen comments to the SIP and Puru Puru drivers. Modified Paths: -------------- kos/kernel/arch/dreamcast/hardware/maple/sip.c kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h kos/kernel/arch/dreamcast/include/dc/maple/sip.h Modified: kos/kernel/arch/dreamcast/hardware/maple/sip.c =================================================================== --- kos/kernel/arch/dreamcast/hardware/maple/sip.c 2010-07-18 03:50:55 UTC (rev 667) +++ kos/kernel/arch/dreamcast/hardware/maple/sip.c 2010-07-18 16:06:42 UTC (rev 668) @@ -359,10 +359,10 @@ sip = (sip_state_t *)dev->status; sip->samples_buf = (uint8 *)malloc(11025 * 2 * 10); - if(sip->samples_buf == NULL) { + if(sip->samples_buf == NULL) { return -1; } - else { + else { sip->is_sampling = 0; sip->amp_gain = SIP_DEFAULT_GAIN; sip->buf_pos = 0; Modified: kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h 2010-07-18 03:50:55 UTC (rev 667) +++ kos/kernel/arch/dreamcast/include/dc/maple/purupuru.h 2010-07-18 16:06:42 UTC (rev 668) @@ -2,10 +2,33 @@ dc/maple/purupuru.h Copyright (C) 2003 Dan Potter - Copyright (C) 2005 Lawrence Sebald + Copyright (C) 2005, 2010 Lawrence Sebald */ +/** \file dc/maple/purupuru.h + \brief Definitions using the Puru Puru (Jump) Pack. + + This file contains the definitions needed to access maple jump pack devices. + Puru Puru was Sega's internal name for the device, hence why its referred to + in this way here. + + This driver is largely based off of information provided by Kamjin on the + DCEmulation forums. See + http://dcemulation.org/phpBB/viewtopic.php?f=29&t=48462 if you're interested + in the original documentation. + + Also, its important to note that not all Jump Packs are created equal. Some + of the stuff in here does not do what it seems like it should on many + devices. The "decay" setting, for instance, does not seem to work on Sega + Puru Purus, and actually makes most (if not all) effects do absolutely + nothing. Basically, its all a big guess-and-test game to get things to work + the way you might like. Don't be surprised if you manage to set up something + that does absolutely nothing on the first try. + + \author Lawrence Sebald +*/ + #ifndef __DC_MAPLE_PURUPURU_H #define __DC_MAPLE_PURUPURU_H @@ -14,18 +37,23 @@ #include <arch/types.h> -/* These defines are based off of information that Kamjin provided on the - DCEmulation forums. They may or may not act the same on all purus. - For instance, on my official Sega Purupuru, the decay setting seems - to make many if not all effects do nothing. Don't be surprised if - your initial effect does nothing for you, its to be expected. Using - the purupuru seems to be very much a guess-and-test situation. */ +/** \brief Effect generation structure. -/* Effect Generation structure, use with the defines below. */ + This structure is used for convenience to send an effect to the jump pack. + This, along with the various macros in this file can give a slightly better + idea of the effect being generated than using the raw values. +*/ typedef struct purupuru_effect { + /** \brief The duration of the effect. No idea on units... */ uint8 duration; + + /** \brief 2nd effect field. */ uint8 effect2; + + /** \brief 1st effect field. */ uint8 effect1; + + /** \brief Special effects field. */ uint8 special; } purupuru_effect_t; @@ -34,41 +62,125 @@ value works with the INTENSITY of effect1 to increase the intensity of the rumble, where UINTENSITY apparently lowers the rumble's intensity somewhat. */ + +/** \brief Upper-nibble of effect2 convenience macro. + + This macro is for setting the upper nibble of the effect2 field of the + purupuru_effect_t. This apparently lowers the rumble's intensity somewhat. + Valid values are 0-7. +*/ #define PURUPURU_EFFECT2_UINTENSITY(x) (x << 4) + +/** \brief Lower-nibble of effect2 convenience macro. + + This macro is for setting the lower nibble of the effect2 field of the + purupuru_effect_t. This value works with the upper nibble of the effect1 + field to increase the intensity of the rumble effect. Valid values are 0-7. + + \see PURUPURU_EFFECT1_INTENSITY +*/ #define PURUPURU_EFFECT2_LINTENSITY(x) (x) /* OR these in with your effect2 value if you feel so inclined. if you or the PULSE effect in here, you probably should also do so with the effect1 one below. */ +/** \brief Give a decay effect to the rumble on some packs. */ #define PURUPURU_EFFECT2_DECAY (8 << 4) + +/** \brief Give a pulse effect to the rumble. + + This probably should be used with PURUPURU_EFFECT1_PULSE as well. + + \see PURUPURU_EFFECT1_PULSE +*/ #define PURUPURU_EFFECT2_PULSE (8) /* Set one value for this in the effect1 field of the effect structure. */ +/** \brief Upper nibble of effect1 convenience macro. + + This macro is for setting the upper nibble of the effect1 field of the + purupuru_effect_t. This value works with the lower nibble of the effect2 + field to increase the intensity of the rumble effect. Valid values are 0-7. + + \see PURUPURU_EFFECT2_LINTENSITY +*/ #define PURUPURU_EFFECT1_INTENSITY(x) (x << 4) /* OR these in with your effect1 value, if you need them. PULSE should probably be used with the PULSE in effect2, as well. POWERSAVE will probably make your purupuru ignore that command. */ +/** \brief Give a pulse effect to the rumble. + + This probably should be used with PURUPURU_EFFECT2_PULSE as well. + + \see PURUPURU_EFFECT2_PULSE +*/ #define PURUPURU_EFFECT1_PULSE (8 << 4) + +/** \brief Ignore this command. + + Most jump packs will ignore commands with this set in effect1, apparently. +*/ #define PURUPURU_EFFECT1_POWERSAVE (15) /* Special Effects and motor select. The normal purupuru packs will only have one motor. Selecting MOTOR2 for these is probably not a good idea. The PULSE setting here supposably creates a sharp pulse effect, when ORed with the special field. */ +/** \brief Select motor #1. + + Most jump packs only have one motor, but on things that do have more than + one motor (like PS1->Dreamcast controller adapters that support rumble), + this selects the first motor. +*/ #define PURUPURU_SPECIAL_MOTOR1 (1 << 4) + +/** \brief Select motor #2. + + Most jump packs only have one motor, but on things that do have more than + one motor (like PS1->Dreamcast controller adapters that support rumble), + this selects the second motor. +*/ #define PURUPURU_SPECIAL_MOTOR2 (1 << 7) + +/** \brief Yet another pulse effect. + + This supposedly creates a sharp pulse effect. +*/ #define PURUPURU_SPECIAL_PULSE (1) -/* Send a specified effect to a specified purupuru */ +/** \brief Send an effect to a jump pack. + + This function sends an effect created with the purupuru_effect_t structure + to a jump pack to be executed. + + \param dev The device to send the command to. + \param effect The effect to send. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent. Try again later. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int purupuru_rumble(maple_device_t *dev, purupuru_effect_t *effect); -/* Send a raw effect to a specified purupuru */ +/** \brief Send a raw effect to a jump pack. + + This function sends an effect to a jump pack to be executed. This is for if + you (for some reason) don't want to use purupuru_effect_t to build the + effect up. + + \param dev The device to send the command to. + \param effect The effect to send. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent. Try again later. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int purupuru_rumble_raw(maple_device_t *dev, uint32 effect); +/* \cond */ /* Init / Shutdown */ int purupuru_init(); void purupuru_shutdown(); +/* \endcond */ __END_DECLS Modified: kos/kernel/arch/dreamcast/include/dc/maple/sip.h =================================================================== --- kos/kernel/arch/dreamcast/include/dc/maple/sip.h 2010-07-18 03:50:55 UTC (rev 667) +++ kos/kernel/arch/dreamcast/include/dc/maple/sip.h 2010-07-18 16:06:42 UTC (rev 668) @@ -1,10 +1,24 @@ /* KallistiOS ##version## dc/maple/sip.h - Copyright (C) 2005, 2008 Lawrence Sebald + Copyright (C) 2005, 2008, 2010 Lawrence Sebald */ +/** \file dc/maple/sip.h + \brief Definitions using the Sound Input Peripheral. + + This file contains the definitions needed to access the Maple microphone + type device (the Seaman mic). Many thanks go out to ZeZu who pointed me + toward what some of the commands actually do in the original version of this + driver. + + As a note, the device itself is actually referred to by the system as the + Sound Input Peripheral, so hence why this driver is named as it is. + + \author Lawrence Sebald +*/ + #ifndef __DC_MAPLE_SIP_H #define __DC_MAPLE_SIP_H @@ -13,81 +27,191 @@ #include <sys/types.h> -/* This driver controls the Sound Input Peripheral for the maple bus (aka, the - microphone that came with Seaman and the Dreameye). Many thanks go out to - ZeZu for pointing me towards what some commands actually do in the original - version of this driver. +/** \brief SIP status structure. + + This structure contains information about the status of the microphone + device and can be fetched with maple_dev_status(). You should not modify + any of the values in here, it is all "read-only" to your programs. Modifying + any of this, especially while the microphone is sampling could really screw + things up. + + \headerfile dc/maple/sip.h */ - -/* SIP Status structure. Everything in here should be considered to be read-only - from user programs. */ typedef struct sip_state { + /** \brief The gain value for the microphone amp. */ int amp_gain; + + /** \brief The type of samples that are being recorded. */ int sample_type; + + /** \brief What frequency are we sampling at? */ int frequency; + + /** \brief Is the mic currently sampling? */ int is_sampling; + + /** \brief How long is the samples buffer? */ size_t buf_len; + + /** \brief What is the last place written to in the buffer? */ off_t buf_pos; + + /** \brief Buffer for storing samples in (automatically allocated). */ uint8 *samples_buf; } sip_state_t; -/* Subcommands of the Microphone command. */ +/** \brief Get recorded samples from the microphone device. + + This subcommand is used with the MAPLE_COMMAND_MICCONTROL command to fetch + samples from the microphone. +*/ #define SIP_SUBCOMMAND_GET_SAMPLES 0x01 + +/** \brief Start and stop sampling. + + This subcommand is used with the MAPLE_COMMAND_MICCONTROL command to start + and stop sampling on the microphone. +*/ #define SIP_SUBCOMMAND_BASIC_CTRL 0x02 -/* The minimum, maximum, and default gain values that can be passed to the - sip_set_gain function. */ +/** \brief Minimum microphone gain. */ #define SIP_MIN_GAIN 0x00 + +/** \brief Default microphone gain. */ #define SIP_DEFAULT_GAIN 0x0F + +/** \brief Maximum microphone gain. */ #define SIP_MAX_GAIN 0x1F -/* Set the amplifier's gain. This should only be called prior to sampling, to - ensure that the sound returned is of the same volume (unlike the other - functions below, this is not strictly a requirement, as this gets sent - with all of the get samples packets). */ +/** \brief Set the microphone's gain value. + + This function sets the gain value of the specified microphone device to + the value given. This should only be called prior to sampling so as to keep + the amplification constant throughout the sampling process, but can be + changed on the fly if you really want to. + + \param dev The microphone device to set gain on. + \param g The value to set as the gain. + \retval MAPLE_EOK On success. + \retval MAPLE_EINVALID If g is out of range. + \see SIP_MIN_GAIN + \see SIP_DEFAULT_GAIN + \see SIP_MAX_GAIN +*/ int sip_set_gain(maple_device_t *dev, unsigned int g); /* Sample types. These two values are the only defined types of samples that the SIP can output. 16-bit signed is your standard 16-bit signed samples, where 8-bit ulaw is obvously encoded as ulaw. */ + +/** \brief Record 16-bit signed integer samples. */ #define SIP_SAMPLE_16BIT_SIGNED 0x00 + +/** \brief Record 8-bit ulaw samples. */ #define SIP_SAMPLE_8BIT_ULAW 0x01 -/* Set the sample type to be returned by the microphone. This must be called - prior to a sip_start_sampling if you want to change it from the default - (16-bit signed is the default). */ +/** \brief Set the sample type to be recorded by the microphone. + + This function sets the sample type that the microphone will return. The + default value for this is 16-bit signed integer samples. You must call this + prior to sip_start_sampling() if you wish to change it from the default. + + \param dev The microphone device to set sample type on. + \param type The type of samples requested. + \retval MAPLE_EOK On success. + \retval MAPLE_EINVALID If type is invalid. + \retval MAPLE_EFAIL If the microphone is sampling. + \see SIP_SAMPLE_16BIT_SIGNED + \see SIP_SAMPLE_8BIT_ULAW +*/ int sip_set_sample_type(maple_device_t *dev, unsigned int type); /* Sampling frequencies. The SIP supports sampling at either 8kHz or 11.025 kHz. One of these values should be passed to the sip_set_frequency function. */ +/** \brief Record samples at 11.025kHz. */ #define SIP_SAMPLE_11KHZ 0x00 + +/** \brief Record samples at 8kHz. */ #define SIP_SAMPLE_8KHZ 0x01 -/* Set the sampling frequency to be returned by the microphone. This must be - called prior to a sip_start_sampling if you want to change it from the - default (11kHz is the default). */ +/** \brief Set the sample frequency to be recorded by the microphone. + + This function sets the sample frequency that the microphone will record. The + default value for this is about 11.025kHz samples. You must call this prior + to sip_start_sampling() if you wish to change it from the default. + + \param dev The microphone device to set sample type on. + \param freq The type of samples requested. + \retval MAPLE_EOK On success. + \retval MAPLE_EINVALID If freq is invalid. + \retval MAPLE_EFAIL If the microphone is sampling. + \see SIP_SAMPLE_11KHZ + \see SIP_SAMPLE_8KHZ +*/ int sip_set_frequency(maple_device_t *dev, unsigned int freq); -/* Start sampling. If you want the function to block until sampling has started, - set the block argument to something other than zero. Otherwise, check the - is_sampling member of the device status to know when sampling has started. */ +/** \brief Start sampling on a microphone. + + This function informs a microphone it should start recording samples. + + \param dev The device to start sampling on. + \param block Set to 1 to wait for the SIP to start sampling. + Otherwise check the is_sampling member of the status + for dev to know when it has started. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent, try again later. + \retval MAPLE_EFAIL If the microphone is already sampling. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int sip_start_sampling(maple_device_t *dev, int block); -/* Stop sampling. Same comment about blocking above applies here too. */ +/** \brief Stop sampling on a microphone. + + This function informs a microphone it should stop recording samples. + + \param dev The device to stop sampling on. + \param block Set to 1 to wait for the SIP to stop sampling. + Otherwise check the is_sampling member of the status + for dev to know when it has finished. + \retval MAPLE_EOK On success. + \retval MAPLE_EAGAIN If the command couldn't be sent, try again later. + \retval MAPLE_EFAIL If the microphone is not sampling. + \retval MAPLE_ETIMEOUT If the command timed out while blocking. +*/ int sip_stop_sampling(maple_device_t *dev, int block); -/* Grab the samples buffer from the device. This function can only be called - when the microphone is not sampling. Once you call this function, you are - responsible for the buffer, so you must free it when you're done. The sz - pointer is used to return how long the sample data is. */ +/** \brief Retrieve the sample buffer from the microphone. + + This function retrieves the sample buffer from the microphone and allocates + a new buffer for the microphone to record into. This function cannot be + called while the microphone is sampling. The caller is responsible for the + buffer returned, and must free the buffer when it is done with it. + + \param dev The device to fetch samples for. + \param sz On return, the size of the sample buffer in bytes. + This must not be NULL. + \return The sample buffer on success, NULL on failure. +*/ uint8 *sip_get_samples(maple_device_t *dev, size_t *sz); -/* Clear the internal sample buffer. */ +/** \brief Clear the sample buffer of a microphone. + + This function clears out any old samples on the microphone buffer so that + recording will start from the beginning of the buffer again. This does not + resize the buffer in any way. This function will not work if called while + the microphone is sampling. + + \param dev The device to clear the buffer on. + \retval MAPLE_EOK On success. + \retval MAPLE_EFAIL If the device is currently sampling. +*/ int sip_clear_samples(maple_device_t *dev); +/* \cond */ /* Init / Shutdown */ int sip_init(); void sip_shutdown(); +/* \endcond */ __END_DECLS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |