This commit was manufactured by cvs2svn to create branch 'RELENG_6'.

This commit is contained in:
cvs2svn 2006-05-25 04:01:05 +00:00
parent c538ede71c
commit 47d76a2b91
33 changed files with 9416 additions and 0 deletions

33
contrib/netcat/atomicio.h Normal file
View File

@ -0,0 +1,33 @@
/* $OpenBSD: atomicio.h,v 1.1 2005/05/24 20:13:28 avsm Exp $ */
/*
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write

View File

@ -0,0 +1,353 @@
/*
* Namespace munging inspired by an equivalent hack in NetBSD's tree: add
* the "ssh_" prefix to every symbol in libssh which doesn't already have
* it. This prevents collisions between symbols in libssh and symbols in
* other libraries or applications which link with libssh, either directly
* or indirectly (e.g. through PAM loading pam_ssh).
*
* A list of symbols which need munging is obtained as follows:
*
* nm libssh.a | awk '$2 == "T" && $3 !~ /^ssh_/ { print $3 }'
*
* $FreeBSD$
*/
#define a2port ssh_a2port
#define a2tun ssh_a2tun
#define acss ssh_acss
#define acss_setkey ssh_acss_setkey
#define acss_setsubkey ssh_acss_setsubkey
#define add_host_to_hostfile ssh_add_host_to_hostfile
#define addargs ssh_addargs
#define ask_permission ssh_ask_permission
#define atomicio ssh_atomicio
#define auth_request_forwarding ssh_auth_request_forwarding
#define buffer_append ssh_buffer_append
#define buffer_append_space ssh_buffer_append_space
#define buffer_clear ssh_buffer_clear
#define buffer_compress ssh_buffer_compress
#define buffer_compress_init_recv ssh_buffer_compress_init_recv
#define buffer_compress_init_send ssh_buffer_compress_init_send
#define buffer_compress_uninit ssh_buffer_compress_uninit
#define buffer_consume ssh_buffer_consume
#define buffer_consume_end ssh_buffer_consume_end
#define buffer_consume_end_ret ssh_buffer_consume_end_ret
#define buffer_consume_ret ssh_buffer_consume_ret
#define buffer_dump ssh_buffer_dump
#define buffer_free ssh_buffer_free
#define buffer_get ssh_buffer_get
#define buffer_get_bignum ssh_buffer_get_bignum
#define buffer_get_bignum2 ssh_buffer_get_bignum2
#define buffer_get_bignum2_ret ssh_buffer_get_bignum2_ret
#define buffer_get_bignum_ret ssh_buffer_get_bignum_ret
#define buffer_get_char ssh_buffer_get_char
#define buffer_get_char_ret ssh_buffer_get_char_ret
#define buffer_get_int ssh_buffer_get_int
#define buffer_get_int64 ssh_buffer_get_int64
#define buffer_get_int64_ret ssh_buffer_get_int64_ret
#define buffer_get_int_ret ssh_buffer_get_int_ret
#define buffer_get_ret ssh_buffer_get_ret
#define buffer_get_short ssh_buffer_get_short
#define buffer_get_short_ret ssh_buffer_get_short_ret
#define buffer_get_string ssh_buffer_get_string
#define buffer_get_string_ret ssh_buffer_get_string_ret
#define buffer_init ssh_buffer_init
#define buffer_len ssh_buffer_len
#define buffer_ptr ssh_buffer_ptr
#define buffer_put_bignum ssh_buffer_put_bignum
#define buffer_put_bignum2 ssh_buffer_put_bignum2
#define buffer_put_bignum2_ret ssh_buffer_put_bignum2_ret
#define buffer_put_bignum_ret ssh_buffer_put_bignum_ret
#define buffer_put_char ssh_buffer_put_char
#define buffer_put_cstring ssh_buffer_put_cstring
#define buffer_put_int ssh_buffer_put_int
#define buffer_put_int64 ssh_buffer_put_int64
#define buffer_put_short ssh_buffer_put_short
#define buffer_put_string ssh_buffer_put_string
#define buffer_uncompress ssh_buffer_uncompress
#define chan_ibuf_empty ssh_chan_ibuf_empty
#define chan_is_dead ssh_chan_is_dead
#define chan_mark_dead ssh_chan_mark_dead
#define chan_obuf_empty ssh_chan_obuf_empty
#define chan_rcvd_ieof ssh_chan_rcvd_ieof
#define chan_rcvd_oclose ssh_chan_rcvd_oclose
#define chan_read_failed ssh_chan_read_failed
#define chan_write_failed ssh_chan_write_failed
#define channel_add_permitted_opens ssh_channel_add_permitted_opens
#define channel_after_select ssh_channel_after_select
#define channel_by_id ssh_channel_by_id
#define channel_cancel_cleanup ssh_channel_cancel_cleanup
#define channel_cancel_rport_listener ssh_channel_cancel_rport_listener
#define channel_clear_permitted_opens ssh_channel_clear_permitted_opens
#define channel_close_all ssh_channel_close_all
#define channel_close_fd ssh_channel_close_fd
#define channel_connect_by_listen_address ssh_channel_connect_by_listen_address
#define channel_connect_to ssh_channel_connect_to
#define channel_find_open ssh_channel_find_open
#define channel_free ssh_channel_free
#define channel_free_all ssh_channel_free_all
#define channel_input_close ssh_channel_input_close
#define channel_input_close_confirmation ssh_channel_input_close_confirmation
#define channel_input_data ssh_channel_input_data
#define channel_input_extended_data ssh_channel_input_extended_data
#define channel_input_ieof ssh_channel_input_ieof
#define channel_input_oclose ssh_channel_input_oclose
#define channel_input_open_confirmation ssh_channel_input_open_confirmation
#define channel_input_open_failure ssh_channel_input_open_failure
#define channel_input_port_forward_request ssh_channel_input_port_forward_request
#define channel_input_port_open ssh_channel_input_port_open
#define channel_input_window_adjust ssh_channel_input_window_adjust
#define channel_lookup ssh_channel_lookup
#define channel_new ssh_channel_new
#define channel_not_very_much_buffered_data ssh_channel_not_very_much_buffered_data
#define channel_open_message ssh_channel_open_message
#define channel_output_poll ssh_channel_output_poll
#define channel_permit_all_opens ssh_channel_permit_all_opens
#define channel_prepare_select ssh_channel_prepare_select
#define channel_register_cleanup ssh_channel_register_cleanup
#define channel_register_confirm ssh_channel_register_confirm
#define channel_register_filter ssh_channel_register_filter
#define channel_request_remote_forwarding ssh_channel_request_remote_forwarding
#define channel_request_rforward_cancel ssh_channel_request_rforward_cancel
#define channel_request_start ssh_channel_request_start
#define channel_send_open ssh_channel_send_open
#define channel_send_window_changes ssh_channel_send_window_changes
#define channel_set_af ssh_channel_set_af
#define channel_set_fds ssh_channel_set_fds
#define channel_setup_local_fwd_listener ssh_channel_setup_local_fwd_listener
#define channel_setup_remote_fwd_listener ssh_channel_setup_remote_fwd_listener
#define channel_still_open ssh_channel_still_open
#define channel_stop_listening ssh_channel_stop_listening
#define check_host_in_hostfile ssh_check_host_in_hostfile
#define choose_dh ssh_choose_dh
#define chop ssh_chop
#define cipher_blocksize ssh_cipher_blocksize
#define cipher_by_name ssh_cipher_by_name
#define cipher_by_number ssh_cipher_by_number
#define cipher_cleanup ssh_cipher_cleanup
#define cipher_crypt ssh_cipher_crypt
#define cipher_get_keycontext ssh_cipher_get_keycontext
#define cipher_get_keyiv ssh_cipher_get_keyiv
#define cipher_get_keyiv_len ssh_cipher_get_keyiv_len
#define cipher_get_number ssh_cipher_get_number
#define cipher_init ssh_cipher_init
#define cipher_keylen ssh_cipher_keylen
#define cipher_mask_ssh1 ssh_cipher_mask_ssh1
#define cipher_name ssh_cipher_name
#define cipher_number ssh_cipher_number
#define cipher_set_key_string ssh_cipher_set_key_string
#define cipher_set_keycontext ssh_cipher_set_keycontext
#define cipher_set_keyiv ssh_cipher_set_keyiv
#define ciphers_valid ssh_ciphers_valid
#define cleanhostname ssh_cleanhostname
#define cleanup_exit ssh_cleanup_exit
#define closefrom ssh_closefrom
#define colon ssh_colon
#define compat_cipher_proposal ssh_compat_cipher_proposal
#define compat_datafellows ssh_compat_datafellows
#define convtime ssh_convtime
#define decode_reply ssh_decode_reply
#define deny_input_open ssh_deny_input_open
#define derive_ssh1_session_id ssh_derive_ssh1_session_id
#define detect_attack ssh_detect_attack
#define dh_estimate ssh_dh_estimate
#define dh_gen_key ssh_dh_gen_key
#define dh_new_group ssh_dh_new_group
#define dh_new_group1 ssh_dh_new_group1
#define dh_new_group14 ssh_dh_new_group14
#define dh_new_group_asc ssh_dh_new_group_asc
#define dh_pub_is_valid ssh_dh_pub_is_valid
#define dispatch_init ssh_dispatch_init
#define dispatch_protocol_error ssh_dispatch_protocol_error
#define dispatch_protocol_ignore ssh_dispatch_protocol_ignore
#define dispatch_range ssh_dispatch_range
#define dispatch_run ssh_dispatch_run
#define dispatch_set ssh_dispatch_set
#define do_log ssh_do_log
#define dump_base64 ssh_dump_base64
#define enable_compat13 ssh_enable_compat13
#define enable_compat20 ssh_enable_compat20
#define evp_acss ssh_evp_acss
#define evp_aes_128_ctr ssh_evp_aes_128_ctr
#define evp_rijndael ssh_evp_rijndael
#define evp_ssh1_3des ssh_evp_ssh1_3des
#define evp_ssh1_bf ssh_evp_ssh1_bf
#define export_dns_rr ssh_export_dns_rr
#define freeargs ssh_freeargs
#define freerrset ssh_freerrset
#define gen_candidates ssh_gen_candidates
#define get_canonical_hostname ssh_get_canonical_hostname
#define get_local_ipaddr ssh_get_local_ipaddr
#define get_local_name ssh_get_local_name
#define get_local_port ssh_get_local_port
#define get_peer_ipaddr ssh_get_peer_ipaddr
#define get_peer_port ssh_get_peer_port
#define get_remote_ipaddr ssh_get_remote_ipaddr
#define get_remote_name_or_ip ssh_get_remote_name_or_ip
#define get_remote_port ssh_get_remote_port
#define getrrsetbyname ssh_getrrsetbyname
#define host_hash ssh_host_hash
#define hostfile_read_key ssh_hostfile_read_key
#define hpdelim ssh_hpdelim
#define init_rng ssh_init_rng
#define ipv64_normalise_mapped ssh_ipv64_normalise_mapped
#define kex_derive_keys ssh_kex_derive_keys
#define kex_dh_hash ssh_kex_dh_hash
#define kex_finish ssh_kex_finish
#define kex_get_newkeys ssh_kex_get_newkeys
#define kex_input_kexinit ssh_kex_input_kexinit
#define kex_send_kexinit ssh_kex_send_kexinit
#define kex_setup ssh_kex_setup
#define kexdh_client ssh_kexdh_client
#define kexgex_client ssh_kexgex_client
#define kexgex_hash ssh_kexgex_hash
#define key_demote ssh_key_demote
#define key_equal ssh_key_equal
#define key_fingerprint ssh_key_fingerprint
#define key_fingerprint_raw ssh_key_fingerprint_raw
#define key_free ssh_key_free
#define key_from_blob ssh_key_from_blob
#define key_from_private ssh_key_from_private
#define key_generate ssh_key_generate
#define key_load_private ssh_key_load_private
#define key_load_private_pem ssh_key_load_private_pem
#define key_load_private_type ssh_key_load_private_type
#define key_load_public ssh_key_load_public
#define key_load_public_type ssh_key_load_public_type
#define key_names_valid2 ssh_key_names_valid2
#define key_new ssh_key_new
#define key_new_private ssh_key_new_private
#define key_read ssh_key_read
#define key_save_private ssh_key_save_private
#define key_sign ssh_key_sign
#define key_size ssh_key_size
#define key_ssh_name ssh_key_ssh_name
#define key_to_blob ssh_key_to_blob
#define key_type ssh_key_type
#define key_type_from_name ssh_key_type_from_name
#define key_verify ssh_key_verify
#define key_write ssh_key_write
#define log_facility_number ssh_log_facility_number
#define log_init ssh_log_init
#define log_level_number ssh_log_level_number
#define lookup_key_in_hostfile_by_type ssh_lookup_key_in_hostfile_by_type
#define mac_compute ssh_mac_compute
#define mac_init ssh_mac_init
#define mac_valid ssh_mac_valid
#define match_host_and_ip ssh_match_host_and_ip
#define match_hostname ssh_match_hostname
#define match_list ssh_match_list
#define match_pattern ssh_match_pattern
#define match_pattern_list ssh_match_pattern_list
#define match_user ssh_match_user
#define mm_receive_fd ssh_mm_receive_fd
#define mm_send_fd ssh_mm_send_fd
#define mysignal ssh_mysignal
#define packet_add_padding ssh_packet_add_padding
#define packet_close ssh_packet_close
#define packet_connection_is_ipv4 ssh_packet_connection_is_ipv4
#define packet_connection_is_on_socket ssh_packet_connection_is_on_socket
#define packet_disconnect ssh_packet_disconnect
#define packet_get_bignum ssh_packet_get_bignum
#define packet_get_bignum2 ssh_packet_get_bignum2
#define packet_get_char ssh_packet_get_char
#define packet_get_connection_in ssh_packet_get_connection_in
#define packet_get_connection_out ssh_packet_get_connection_out
#define packet_get_encryption_key ssh_packet_get_encryption_key
#define packet_get_int ssh_packet_get_int
#define packet_get_keycontext ssh_packet_get_keycontext
#define packet_get_keyiv ssh_packet_get_keyiv
#define packet_get_keyiv_len ssh_packet_get_keyiv_len
#define packet_get_protocol_flags ssh_packet_get_protocol_flags
#define packet_get_raw ssh_packet_get_raw
#define packet_get_ssh1_cipher ssh_packet_get_ssh1_cipher
#define packet_get_state ssh_packet_get_state
#define packet_get_string ssh_packet_get_string
#define packet_have_data_to_write ssh_packet_have_data_to_write
#define packet_is_interactive ssh_packet_is_interactive
#define packet_need_rekeying ssh_packet_need_rekeying
#define packet_not_very_much_data_to_write ssh_packet_not_very_much_data_to_write
#define packet_process_incoming ssh_packet_process_incoming
#define packet_put_bignum ssh_packet_put_bignum
#define packet_put_bignum2 ssh_packet_put_bignum2
#define packet_put_char ssh_packet_put_char
#define packet_put_cstring ssh_packet_put_cstring
#define packet_put_int ssh_packet_put_int
#define packet_put_raw ssh_packet_put_raw
#define packet_put_string ssh_packet_put_string
#define packet_read ssh_packet_read
#define packet_read_expect ssh_packet_read_expect
#define packet_read_poll ssh_packet_read_poll
#define packet_read_poll_seqnr ssh_packet_read_poll_seqnr
#define packet_read_seqnr ssh_packet_read_seqnr
#define packet_remaining ssh_packet_remaining
#define packet_send ssh_packet_send
#define packet_send_debug ssh_packet_send_debug
#define packet_send_ignore ssh_packet_send_ignore
#define packet_set_authenticated ssh_packet_set_authenticated
#define packet_set_connection ssh_packet_set_connection
#define packet_set_encryption_key ssh_packet_set_encryption_key
#define packet_set_interactive ssh_packet_set_interactive
#define packet_set_iv ssh_packet_set_iv
#define packet_set_keycontext ssh_packet_set_keycontext
#define packet_set_maxsize ssh_packet_set_maxsize
#define packet_set_nonblocking ssh_packet_set_nonblocking
#define packet_set_protocol_flags ssh_packet_set_protocol_flags
#define packet_set_rekey_limit ssh_packet_set_rekey_limit
#define packet_set_server ssh_packet_set_server
#define packet_set_state ssh_packet_set_state
#define packet_start ssh_packet_start
#define packet_start_compression ssh_packet_start_compression
#define packet_write_poll ssh_packet_write_poll
#define packet_write_wait ssh_packet_write_wait
#define percent_expand ssh_percent_expand
#define permanently_set_uid ssh_permanently_set_uid
#define prime_test ssh_prime_test
#define proto_spec ssh_proto_spec
#define pwcopy ssh_pwcopy
#define read_keyfile_line ssh_read_keyfile_line
#define read_passphrase ssh_read_passphrase
#define refresh_progress_meter ssh_refresh_progress_meter
#define replacearg ssh_replacearg
#define restore_uid ssh_restore_uid
#define rijndael_decrypt ssh_rijndael_decrypt
#define rijndael_encrypt ssh_rijndael_encrypt
#define rijndael_set_key ssh_rijndael_set_key
#define rsa_generate_additional_parameters ssh_rsa_generate_additional_parameters
#define rsa_private_decrypt ssh_rsa_private_decrypt
#define rsa_public_encrypt ssh_rsa_public_encrypt
#define sanitise_stdfd ssh_sanitise_stdfd
#define seed_rng ssh_seed_rng
#define set_newkeys ssh_set_newkeys
#define set_nodelay ssh_set_nodelay
#define set_nonblock ssh_set_nonblock
#define shadow_pw ssh_shadow_pw
#define ssh1_3des_iv ssh_ssh1_3des_iv
#define start_progress_meter ssh_start_progress_meter
#define stop_progress_meter ssh_stop_progress_meter
#define strdelim ssh_strdelim
#define strnvis ssh_strnvis
#define strvis ssh_strvis
#define strvisx ssh_strvisx
#define sys_tun_open ssh_sys_tun_open
#define temporarily_use_uid ssh_temporarily_use_uid
#define tilde_expand_filename ssh_tilde_expand_filename
#define tohex ssh_tohex
#define tty_make_modes ssh_tty_make_modes
#define tty_parse_modes ssh_tty_parse_modes
#define tun_open ssh_tun_open
#define unset_nonblock ssh_unset_nonblock
#define uudecode ssh_uudecode
#define uuencode ssh_uuencode
#define verify_host_key_dns ssh_verify_host_key_dns
#define vis ssh_vis
#define x11_connect_display ssh_x11_connect_display
#define x11_create_display_inet ssh_x11_create_display_inet
#define x11_input_open ssh_x11_input_open
#define x11_request_forwarding_with_spoofing ssh_x11_request_forwarding_with_spoofing
#define xcrypt ssh_xcrypt
#define xfree ssh_xfree
#define xmalloc ssh_xmalloc
#define xmmap ssh_xmmap
#define xrealloc ssh_xrealloc
#define xstrdup ssh_xstrdup

71
include/res_update.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999 by Internet Software Consortium, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* $Id: res_update.h,v 1.1.206.1 2004/03/09 08:33:29 marka Exp $
* $FreeBSD$
*/
#ifndef __RES_UPDATE_H
#define __RES_UPDATE_H
#include <sys/types.h>
#include <arpa/nameser.h>
#include <resolv.h>
/*
* This RR-like structure is particular to UPDATE.
*/
struct ns_updrec {
struct {
struct ns_updrec *prev;
struct ns_updrec *next;
} r_link, r_glink;
ns_sect r_section; /* ZONE/PREREQUISITE/UPDATE */
char * r_dname; /* owner of the RR */
ns_class r_class; /* class number */
ns_type r_type; /* type number */
u_int32_t r_ttl; /* time to live */
u_char * r_data; /* rdata fields as text string */
u_int r_size; /* size of r_data field */
int r_opcode; /* type of operation */
/* following fields for private use by the resolver/server routines */
struct databuf *r_dp; /* databuf to process */
struct databuf *r_deldp; /* databuf's deleted/overwritten */
u_int r_zone; /* zone number on server */
};
typedef struct ns_updrec ns_updrec;
typedef struct {
ns_updrec *head;
ns_updrec *tail;
} ns_updque;
#define res_mkupdate __res_mkupdate
#define res_update __res_update
#define res_mkupdrec __res_mkupdrec
#define res_freeupdrec __res_freeupdrec
#define res_nmkupdate __res_nmkupdate
#define res_nupdate __res_nupdate
int res_mkupdate(ns_updrec *, u_char *, int);
int res_update(ns_updrec *);
ns_updrec * res_mkupdrec(int, const char *, u_int, u_int, u_long);
void res_freeupdrec(ns_updrec *);
int res_nmkupdate(res_state, ns_updrec *, u_char *, int);
int res_nupdate(res_state, ns_updrec *, ns_tsig_key *);
#endif /*__RES_UPDATE_H*/

View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef lint
static const char rcsid[] = "$Id: ns_samedomain.c,v 1.1.2.2.4.2 2004/03/16 12:34:17 marka Exp $";
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "port_before.h"
#include <sys/types.h>
#include <arpa/nameser.h>
#include <errno.h>
#include <string.h>
#include "port_after.h"
/*
* int
* ns_samedomain(a, b)
* Check whether a name belongs to a domain.
* Inputs:
* a - the domain whose ancestory is being verified
* b - the potential ancestor we're checking against
* Return:
* boolean - is a at or below b?
* Notes:
* Trailing dots are first removed from name and domain.
* Always compare complete subdomains, not only whether the
* domain name is the trailing string of the given name.
*
* "host.foobar.top" lies in "foobar.top" and in "top" and in ""
* but NOT in "bar.top"
*/
int
ns_samedomain(const char *a, const char *b) {
size_t la, lb;
int diff, i, escaped;
const char *cp;
la = strlen(a);
lb = strlen(b);
/* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
if (la != 0U && a[la - 1] == '.') {
escaped = 0;
/* Note this loop doesn't get executed if la==1. */
for (i = la - 2; i >= 0; i--)
if (a[i] == '\\') {
if (escaped)
escaped = 0;
else
escaped = 1;
} else
break;
if (!escaped)
la--;
}
/* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
if (lb != 0U && b[lb - 1] == '.') {
escaped = 0;
/* note this loop doesn't get executed if lb==1 */
for (i = lb - 2; i >= 0; i--)
if (b[i] == '\\') {
if (escaped)
escaped = 0;
else
escaped = 1;
} else
break;
if (!escaped)
lb--;
}
/* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
if (lb == 0U)
return (1);
/* 'b' longer than 'a' means 'a' can't be in 'b'. */
if (lb > la)
return (0);
/* 'a' and 'b' being equal at this point indicates sameness. */
if (lb == la)
return (strncasecmp(a, b, lb) == 0);
/* Ok, we know la > lb. */
diff = la - lb;
/*
* If 'a' is only 1 character longer than 'b', then it can't be
* a subdomain of 'b' (because of the need for the '.' label
* separator).
*/
if (diff < 2)
return (0);
/*
* If the character before the last 'lb' characters of 'b'
* isn't '.', then it can't be a match (this lets us avoid
* having "foobar.com" match "bar.com").
*/
if (a[diff - 1] != '.')
return (0);
/*
* We're not sure about that '.', however. It could be escaped
* and thus not a really a label separator.
*/
escaped = 0;
for (i = diff - 2; i >= 0; i--)
if (a[i] == '\\') {
if (escaped)
escaped = 0;
else
escaped = 1;
} else
break;
if (escaped)
return (0);
/* Now compare aligned trailing substring. */
cp = a + diff;
return (strncasecmp(cp, b, lb) == 0);
}
#ifndef _LIBC
/*
* int
* ns_subdomain(a, b)
* is "a" a subdomain of "b"?
*/
int
ns_subdomain(const char *a, const char *b) {
return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
}
#endif
/*
* int
* ns_makecanon(src, dst, dstsize)
* make a canonical copy of domain name "src"
* notes:
* foo -> foo.
* foo. -> foo.
* foo.. -> foo.
* foo\. -> foo\..
* foo\\. -> foo\\.
*/
int
ns_makecanon(const char *src, char *dst, size_t dstsize) {
size_t n = strlen(src);
if (n + sizeof "." > dstsize) { /* Note: sizeof == 2 */
errno = EMSGSIZE;
return (-1);
}
strcpy(dst, src);
while (n >= 1U && dst[n - 1] == '.') /* Ends in "." */
if (n >= 2U && dst[n - 2] == '\\' && /* Ends in "\." */
(n < 3U || dst[n - 3] != '\\')) /* But not "\\." */
break;
else
dst[--n] = '\0';
dst[n++] = '.';
dst[n] = '\0';
return (0);
}
/*
* int
* ns_samename(a, b)
* determine whether domain name "a" is the same as domain name "b"
* return:
* -1 on error
* 0 if names differ
* 1 if names are the same
*/
int
ns_samename(const char *a, const char *b) {
char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
if (ns_makecanon(a, ta, sizeof ta) < 0 ||
ns_makecanon(b, tb, sizeof tb) < 0)
return (-1);
if (strcasecmp(ta, tb) == 0)
return (1);
else
return (0);
}

View File

@ -0,0 +1,10 @@
# $FreeBSD$
# resolv sources
.PATH: ${.CURDIR}/resolv
SRCS+= herror.c h_errno.c mtctxres.c res_comp.c res_data.c res_debug.c \
res_findzonecut.c res_init.c res_mkquery.c res_mkupdate.c \
res_query.c res_send.c res_state.c res_update.c
SYM_MAPS+= ${.CURDIR}/resolv/Symbol.map

46
lib/libc/resolv/h_errno.c Normal file
View File

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2006 The FreeBSD Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#undef h_errno
extern int h_errno;
int *
__h_errno(void)
{
return (&__res_state()->res_h_errno);
}
void
__h_errno_set(res_state res, int err)
{
h_errno = res->res_h_errno = err;
}

View File

@ -0,0 +1,87 @@
/*-
* Copyright (c) 2006 The FreeBSD Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdlib.h>
#include "namespace.h"
#include "reentrant.h"
#include "un-namespace.h"
#undef _res
struct __res_state _res;
static thread_key_t res_key;
static once_t res_init_once = ONCE_INITIALIZER;
static int res_thr_keycreated = 0;
static void
free_res(void *ptr)
{
res_state statp = ptr;
if (statp->_u._ext.ext != NULL)
res_ndestroy(statp);
free(statp);
}
static void
res_keycreate(void)
{
res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0;
}
res_state
__res_state(void)
{
res_state statp;
if (thr_main() != 0)
return (&_res);
if (thr_once(&res_init_once, res_keycreate) != 0 ||
!res_thr_keycreated)
return (&_res);
statp = thr_getspecific(res_key);
if (statp != NULL)
return (statp);
statp = calloc(1, sizeof(*statp));
if (statp == NULL)
return (&_res);
#ifdef __BIND_RES_TEXT
statp->options = RES_TIMEOUT; /* Motorola, et al. */
#endif
if (thr_setspecific(res_key, statp) == 0)
return (statp);
free(statp);
return (&_res);
}

76
lib/libutil/kld.c Normal file
View File

@ -0,0 +1,76 @@
/*-
* Copyright (c) 2006 Dag-Erling Coïdan Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <errno.h>
#include <libutil.h>
#include <string.h>
int
kld_isloaded(const char *name)
{
struct kld_file_stat fstat;
struct module_stat mstat;
const char *ko;
int fid, mid;
for (fid = kldnext(0); fid > 0; fid = kldnext(fid)) {
fstat.version = sizeof(fstat);
if (kldstat(fid, &fstat) != 0)
continue;
/* check if the file name matches the supplied name */
if (strcmp(fstat.name, name) == 0)
return (1);
/* strip .ko and try again */
if ((ko = strstr(fstat.name, ".ko")) != NULL &&
strlen(name) == (size_t)(ko - fstat.name) &&
strncmp(fstat.name, name, ko - fstat.name) == 0)
return (1);
/* look for a matching module within the file */
for (mid = kldfirstmod(fid); mid > 0; mid = modfnext(mid)) {
mstat.version = sizeof(mstat);
if (modstat(mid, &mstat) != 0)
continue;
if (strcmp(mstat.name, name) == 0)
return (1);
}
}
return (0);
}
int
kld_load(const char *name)
{
if (kldload(name) == -1 && errno != EEXIST)
return (-1);
return (0);
}

85
share/man/man5/linsysfs.5 Normal file
View File

@ -0,0 +1,85 @@
.\" Written by Garrett Wollman
.\" This file is in the public domain.
.\"
.\" $FreeBSD$
.\"
.Dd May 6, 2006
.Dt LINSYSFS 5
.Os
.Sh NAME
.Nm linsysfs
.Nd Linux system file system
.Sh SYNOPSIS
.Bd -literal
linsys /compat/linux/sys linsysfs rw 0 0
.Ed
.Sh DESCRIPTION
The Linux system file system, or
.Nm ,
emulates a subset of the Linux sys file system and is required for
the complete operation of some Linux binaries.
.Pp
The
.Nm
provides a two-level view of devices.
At the highest level, PCI devices themselves are named, according to
their bus, slot and function in the system hierachy.
PCI storage devices are listed in the scsi_host class with a device sym-link
to the PCI directories of the devices.
.Pp
Each device node is a directory containing some files and directories:
.Bl -tag -width status
.It Pa host
A place holder for storage
.Pa host
information.
.It Pa pci_id
A directory for the
.Pa pci_id
that contains either the device information or another directory structure
for a PCI bridge.
.El
.Pp
Each host node of scsi_host is a directory containing some files and directories:
.Bl -tag -width proc_name
.It Pa proc_name
The Linux registered driver name for these devices.
.It Pa device
A sym-link to the PCI
.Pa device
directory.
.El
.Sh FILES
.Bl -tag -width /compat/linux/sys/devices/pci0000:00 -compact
.It Pa /compat/linux/sys
The normal mount point for the
.Nm .
.It Pa /compat/linux/sys/class/scsi_host
The storage host node.
.It Pa /compat/linux/sys/devices/pci0000:00
The PCI device hierarchy node.
.El
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr linprocfs 5 ,
.Xr pseudofs 9
.Sh HISTORY
The
.Nm
first appeared in
.Fx 7.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
was derived from
.Nm linprocfs
by
.An Doug Ambrisko .
This manual page was edited by
.An Doug Ambrisko ,
based on the
.Xr linprocfs 5
manual page by
.An Garrett Wollman .

674
sys/arm/at91/at91.c Normal file
View File

@ -0,0 +1,674 @@
/*-
* Copyright (c) 2005 Olivier Houchard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/pmap.h>
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
#define _ARM32_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/intr.h>
#include <arm/at91/at91rm92reg.h>
#include <arm/at91/at91var.h>
static struct at91_softc *at91_softc;
static int
at91_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
bus_space_handle_t *bshp)
{
vm_paddr_t pa, endpa;
pa = trunc_page(bpa);
if (pa >= 0xfff00000)
return (0);
endpa = round_page(bpa + size);
*bshp = (vm_offset_t)pmap_mapdev(pa, endpa - pa);
return (0);
}
static void
at91_bs_unmap(void *t, bus_size_t size)
{
vm_offset_t va, endva;
va = trunc_page((vm_offset_t)t);
endva = va + round_page(size);
/* Free the kernel virtual mapping. */
kmem_free(kernel_map, va, endva - va);
}
static int
at91_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset,
bus_size_t size, bus_space_handle_t *nbshp)
{
*nbshp = bsh + offset;
return (0);
}
static void
at91_barrier(void *t, bus_space_handle_t bsh, bus_size_t size, bus_size_t b,
int a)
{
}
bs_protos(generic);
bs_protos(generic_armv4);
struct bus_space at91_bs_tag = {
/* cookie */
(void *) 0,
/* mapping/unmapping */
at91_bs_map,
at91_bs_unmap,
at91_bs_subregion,
/* allocation/deallocation */
NULL,
NULL,
/* barrier */
at91_barrier,
/* read (single) */
generic_bs_r_1,
generic_armv4_bs_r_2,
generic_bs_r_4,
NULL,
/* read multiple */
generic_bs_rm_1,
generic_armv4_bs_rm_2,
generic_bs_rm_4,
NULL,
/* read region */
generic_bs_rr_1,
generic_armv4_bs_rr_2,
generic_bs_rr_4,
NULL,
/* write (single) */
generic_bs_w_1,
generic_armv4_bs_w_2,
generic_bs_w_4,
NULL,
/* write multiple */
generic_bs_wm_1,
generic_armv4_bs_wm_2,
generic_bs_wm_4,
NULL,
/* write region */
NULL,
generic_armv4_bs_wr_2,
generic_bs_wr_4,
NULL,
/* set multiple */
NULL,
NULL,
NULL,
NULL,
/* set region */
NULL,
generic_armv4_bs_sr_2,
generic_bs_sr_4,
NULL,
/* copy */
NULL,
generic_armv4_bs_c_2,
NULL,
NULL,
};
static int
at91_probe(device_t dev)
{
device_set_desc(dev, "AT91RM9200 device bus");
return (0);
}
static void
at91_identify(driver_t *drv, device_t parent)
{
BUS_ADD_CHILD(parent, 0, "atmelarm", 0);
}
struct arm32_dma_range *
bus_dma_get_range(void)
{
return (NULL);
}
int
bus_dma_get_range_nb(void)
{
return (0);
}
extern void irq_entry(void);
static void
at91_add_child(device_t dev, int prio, const char *name, int unit,
bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
{
device_t kid;
struct at91_ivar *ivar;
kid = device_add_child_ordered(dev, prio, name, unit);
if (kid == NULL) {
printf("Can't add child %s%d ordered\n", name, unit);
return;
}
ivar = malloc(sizeof(*ivar), M_DEVBUF, M_WAITOK | M_ZERO);
if (ivar == NULL) {
device_delete_child(dev, kid);
printf("Can't add alloc ivar\n");
return;
}
device_set_ivars(kid, ivar);
resource_list_init(&ivar->resources);
if (irq0 != -1)
bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
if (irq1 != 0)
bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
if (irq2 != 0)
bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
if (addr != 0)
bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
}
struct cpu_devs
{
const char *name;
int unit;
bus_addr_t mem_base;
bus_size_t mem_len;
int irq0;
int irq1;
int irq2;
};
struct cpu_devs at91rm9200_devs[] =
{
// All the "system" devices
{
"at91_st", 0,
AT91RM92_BASE + AT91RM92_ST_BASE, AT91RM92_ST_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_pio", 0,
AT91RM92_BASE + AT91RM92_PIOA_BASE, AT91RM92_PIO_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_pio", 1,
AT91RM92_BASE + AT91RM92_PIOB_BASE, AT91RM92_PIO_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_pio", 2,
AT91RM92_BASE + AT91RM92_PIOC_BASE, AT91RM92_PIO_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_pio", 3,
AT91RM92_BASE + AT91RM92_PIOD_BASE, AT91RM92_PIO_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_pmc", 0,
AT91RM92_BASE + AT91RM92_PMC_BASE, AT91RM92_PMC_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_aic", 0,
AT91RM92_BASE + AT91RM92_AIC_BASE, AT91RM92_AIC_SIZE,
0 // Interrupt controller has no interrupts!
},
{
"at91_rtc", 0,
AT91RM92_BASE + AT91RM92_RTC_BASE, AT91RM92_RTC_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"at91_mc", 0,
AT91RM92_BASE + AT91RM92_MC_BASE, AT91RM92_MC_SIZE,
AT91RM92_IRQ_SYSTEM
},
// All other devices
{
"at91_tc", 0,
AT91RM92_BASE + AT91RM92_TC0_BASE, AT91RM92_TC_SIZE,
AT91RM92_IRQ_TC0, AT91RM92_IRQ_TC1, AT91RM92_IRQ_TC2
},
{
"at91_tc", 1,
AT91RM92_BASE + AT91RM92_TC1_BASE, AT91RM92_TC_SIZE,
AT91RM92_IRQ_TC3, AT91RM92_IRQ_TC4, AT91RM92_IRQ_TC5
},
{
"at91_udp", 0,
AT91RM92_BASE + AT91RM92_UDP_BASE, AT91RM92_UDP_SIZE,
AT91RM92_IRQ_UDP
},
{
"at91_mci", 0,
AT91RM92_BASE + AT91RM92_MCI_BASE, AT91RM92_MCI_SIZE,
AT91RM92_IRQ_MCI
},
{
"at91_twi", 0,
AT91RM92_BASE + AT91RM92_TWI_BASE, AT91RM92_TWI_SIZE,
AT91RM92_IRQ_TWI
},
{
"ate", 0,
AT91RM92_BASE + AT91RM92_EMAC_BASE, AT91RM92_EMAC_SIZE,
AT91RM92_IRQ_EMAC
},
#ifndef SKYEYE_WORKAROUNDS
{
"uart", 0,
AT91RM92_BASE + AT91RM92_DBGU_BASE, AT91RM92_DBGU_SIZE,
AT91RM92_IRQ_SYSTEM
},
{
"uart", 1,
AT91RM92_BASE + AT91RM92_USART0_BASE, AT91RM92_USART_SIZE,
AT91RM92_IRQ_USART0
},
{
"uart", 2,
AT91RM92_BASE + AT91RM92_USART1_BASE, AT91RM92_USART_SIZE,
AT91RM92_IRQ_USART1
},
{
"uart", 3,
AT91RM92_BASE + AT91RM92_USART2_BASE, AT91RM92_USART_SIZE,
AT91RM92_IRQ_USART2
},
{
"uart", 4,
AT91RM92_BASE + AT91RM92_USART3_BASE, AT91RM92_USART_SIZE,
AT91RM92_IRQ_USART3
},
#else
{
"uart", 0,
AT91RM92_BASE + AT91RM92_USART0_BASE, AT91RM92_USART_SIZE,
AT91RM92_IRQ_USART0
},
#endif
{
"at91_ssc", 0,
AT91RM92_BASE + AT91RM92_SSC0_BASE, AT91RM92_SSC_SIZE,
AT91RM92_IRQ_SSC0
},
{
"at91_ssc", 1,
AT91RM92_BASE + AT91RM92_SSC1_BASE, AT91RM92_SSC_SIZE,
AT91RM92_IRQ_SSC1
},
{
"at91_ssc", 2,
AT91RM92_BASE + AT91RM92_SSC2_BASE, AT91RM92_SSC_SIZE,
AT91RM92_IRQ_SSC2
},
{
"at91_spi", 0,
AT91RM92_BASE + AT91RM92_SPI_BASE, AT91RM92_SPI_SIZE,
AT91RM92_IRQ_SPI
},
{
"ohci", 0,
AT91RM92_OHCI_BASE, AT91RM92_OHCI_SIZE,
AT91RM92_IRQ_UHP
},
{ 0, 0, 0, 0, 0 }
};
static void
at91_cpu_add_builtin_children(device_t dev, struct at91_softc *sc)
{
int i;
struct cpu_devs *walker;
// XXX should look at the device id in the DBGU register and
// XXX based on the CPU load in these devices
for (i = 0, walker = at91rm9200_devs; walker->name; i++, walker++) {
at91_add_child(dev, i, walker->name, walker->unit,
walker->mem_base, walker->mem_len, walker->irq0,
walker->irq1, walker->irq2);
}
}
#define NORMDEV 50
static int
at91_attach(device_t dev)
{
struct at91_softc *sc = device_get_softc(dev);
int i;
at91_softc = sc;
sc->sc_st = &at91_bs_tag;
sc->sc_sh = AT91RM92_BASE;
sc->dev = dev;
if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
panic("Enable to map IRQ registers");
sc->sc_irq_rman.rm_type = RMAN_ARRAY;
sc->sc_irq_rman.rm_descr = "AT91RM92 IRQs";
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
sc->sc_mem_rman.rm_descr = "AT91RM92 Memory";
#if 0
sc->sc_usbmem_rman.rm_type = RMAN_ARRAY;
sc->sc_usbmem_rman.rm_descr = "AT91RM92 USB Memory-mapped regs";
#endif
if (rman_init(&sc->sc_irq_rman) != 0 ||
rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
panic("at91_attach: failed to set up IRQ rman");
if (rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_mem_rman, 0xfff00000ul,
0xfffffffful) != 0)
panic("at91_attach: failed to set up memory rman");
if (rman_manage_region(&sc->sc_mem_rman, AT91RM92_OHCI_BASE,
AT91RM92_OHCI_BASE + AT91RM92_OHCI_SIZE - 1) != 0)
panic("at91_attach: failed to set up ohci memory");
for (i = 0; i < 32; i++) {
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SVR +
i * 4, i);
/* Priority. */
/* XXX: Give better priorities to IRQs */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SMR + i * 4,
0);
if (i < 8)
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_EOICR,
1);
}
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SPU, 32);
/* No debug. */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_DCR, 0);
/* Disable and clear all interrupts. */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR, 0xffffffff);
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_ICCR, 0xffffffff);
/* XXX */
/* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);
/* DIsable all interrupts for DBGU */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0x20c, 0xffffffff);
/* Disable all interrupts for the SDRAM controller */
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);
at91_cpu_add_builtin_children(dev, sc);
bus_generic_probe(dev);
bus_generic_attach(dev);
enable_interrupts(I32_bit | F32_bit);
return (0);
}
static struct resource *
at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct at91_softc *sc = device_get_softc(dev);
struct resource_list_entry *rle;
struct at91_ivar *ivar = device_get_ivars(child);
struct resource_list *rl = &ivar->resources;
if (device_get_parent(child) != dev)
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
rle = resource_list_find(rl, type, *rid);
if (rle == NULL)
return (NULL);
if (rle->res)
panic("Resource rid %d type %d already in use", *rid, type);
if (start == 0UL && end == ~0UL) {
start = rle->start;
count = ulmax(count, rle->count);
end = ulmax(rle->end, start + count - 1);
}
switch (type)
{
case SYS_RES_IRQ:
rle->res = rman_reserve_resource(&sc->sc_irq_rman,
start, end, count, flags, child);
break;
case SYS_RES_MEMORY:
#if 0
if (start >= 0x00300000 && start <= 0x003fffff)
rle->res = rman_reserve_resource(&sc->sc_usbmem_rman,
start, end, count, flags, child);
else
#endif
rle->res = rman_reserve_resource(&sc->sc_mem_rman,
start, end, count, flags, child);
rman_set_bustag(rle->res, &at91_bs_tag);
rman_set_bushandle(rle->res, start);
break;
}
if (rle->res) {
rle->start = rman_get_start(rle->res);
rle->end = rman_get_end(rle->res);
rle->count = count;
rman_set_rid(rle->res, *rid);
}
return (rle->res);
}
static struct resource_list *
at91_get_resource_list(device_t dev, device_t child)
{
struct at91_ivar *ivar;
ivar = device_get_ivars(child);
return (&(ivar->resources));
}
static int
at91_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = at91_get_resource_list(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
at91_setup_intr(device_t dev, device_t child,
struct resource *ires, int flags, driver_intr_t *intr, void *arg,
void **cookiep)
{
struct at91_softc *sc = device_get_softc(dev);
if (rman_get_start(ires) == AT91RM92_IRQ_SYSTEM && !(flags & INTR_FAST))
panic("All system interrupt ISRs must be type INTR_FAST");
BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, intr, arg,
cookiep);
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IECR,
1 << rman_get_start(ires));
return (0);
}
static int
at91_teardown_intr(device_t dev, device_t child, struct resource *res,
void *cookie)
{
struct at91_softc *sc = device_get_softc(dev);
bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR,
1 << rman_get_start(res));
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
}
static int
at91_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
#if 0
u_long p;
int error;
if (type == SYS_RES_MEMORY) {
error = bus_space_map(rman_get_bustag(r),
rman_get_bushandle(r), rman_get_size(r), 0, &p);
if (error)
return (error);
rman_set_bushandle(r, p);
}
#endif
return (rman_activate_resource(r));
}
static int
at91_print_child(device_t dev, device_t child)
{
struct at91_ivar *ivars;
struct resource_list *rl;
int retval = 0;
ivars = device_get_ivars(child);
rl = &ivars->resources;
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
retval += bus_print_child_footer(dev, child);
return (retval);
}
void
arm_mask_irq(uintptr_t nb)
{
bus_space_write_4(at91_softc->sc_st,
at91_softc->sc_sys_sh, IC_IDCR, 1 << nb);
}
int
arm_get_next_irq()
{
int status;
int irq;
irq = bus_space_read_4(at91_softc->sc_st,
at91_softc->sc_sys_sh, IC_IVR);
status = bus_space_read_4(at91_softc->sc_st,
at91_softc->sc_sys_sh, IC_ISR);
if (status == 0) {
bus_space_write_4(at91_softc->sc_st,
at91_softc->sc_sys_sh, IC_EOICR, 1);
return (-1);
}
return (irq);
}
void
arm_unmask_irq(uintptr_t nb)
{
bus_space_write_4(at91_softc->sc_st,
at91_softc->sc_sys_sh, IC_IECR, 1 << nb);
bus_space_write_4(at91_softc->sc_st, at91_softc->sc_sys_sh,
IC_EOICR, 0);
}
static device_method_t at91_methods[] = {
DEVMETHOD(device_probe, at91_probe),
DEVMETHOD(device_attach, at91_attach),
DEVMETHOD(device_identify, at91_identify),
DEVMETHOD(bus_alloc_resource, at91_alloc_resource),
DEVMETHOD(bus_setup_intr, at91_setup_intr),
DEVMETHOD(bus_teardown_intr, at91_teardown_intr),
DEVMETHOD(bus_activate_resource, at91_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_get_resource_list,at91_get_resource_list),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_release_resource, at91_release_resource),
DEVMETHOD(bus_print_child, at91_print_child),
{0, 0},
};
static driver_t at91_driver = {
"atmelarm",
at91_methods,
sizeof(struct at91_softc),
};
static devclass_t at91_devclass;
DRIVER_MODULE(atmelarm, nexus, at91_driver, at91_devclass, 0, 0);

View File

@ -0,0 +1,47 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
#ifndef ARM_AT91_AT91_PDCREG_H
#define ARM_AT91_AT91_PDCREG_H
#define PDC_RPR 0x100 /* PDC Receive Pointer Register */
#define PDC_RCR 0x104 /* PDC Receive Counter Register */
#define PDC_TPR 0x108 /* PDC Transmit Pointer Register */
#define PDC_TCR 0x10c /* PDC Transmit Counter Register */
#define PDC_RNPR 0x110 /* PDC Receive Next Pointer Register */
#define PDC_RNCR 0x114 /* PDC Receive Next Counter Register */
#define PDC_TNPR 0x118 /* PDC Transmit Next Pointer Reg */
#define PDC_TNCR 0x11c /* PDC Transmit Next Counter Reg */
#define PDC_PTCR 0x120 /* PDC Transfer Control Register */
#define PDC_PTSR 0x124 /* PDC Transfer Status Register */
/* PTCR/PTSR */
#define PDC_PTCR_RXTEN (1UL << 0) /* RXTEN: Receiver Transfer Enable */
#define PDC_PTCR_RXTDIS (1UL << 1) /* RXTDIS: Receiver Transfer Disable */
#define PDC_PTCR_TXTEN (1UL << 8) /* TXTEN: Transmitter Transfer En */
#define PDC_PTCR_TXTDIS (1UL << 9) /* TXTDIS: Transmitter Transmit Dis */
#endif /* ARM_AT91_AT91_PDCREG_H */

232
sys/arm/at91/at91_st.c Normal file
View File

@ -0,0 +1,232 @@
/*-
* Copyright (c) 2005 Olivier Houchard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/time.h>
#include <sys/bus.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/resource.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <arm/at91/at91rm92reg.h>
#include <arm/at91/at91var.h>
#include <arm/at91/at91_streg.h>
static struct at91st_softc {
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
device_t dev;
} *timer_softc;
#define RD4(off) \
bus_space_read_4(timer_softc->sc_st, timer_softc->sc_sh, (off))
#define WR4(off, val) \
bus_space_write_4(timer_softc->sc_st, timer_softc->sc_sh, (off), (val))
static inline int
st_crtr(void)
{
int cur1, cur2;
do {
cur1 = RD4(ST_CRTR);
cur2 = RD4(ST_CRTR);
} while (cur1 != cur2);
return (cur1);
}
static unsigned at91st_get_timecount(struct timecounter *tc);
static struct timecounter at91st_timecounter = {
at91st_get_timecount, /* get_timecount */
NULL, /* no poll_pps */
#ifdef SKYEYE_WORKAROUNDS
0xffffffffu, /* counter_mask */
#else
0xfffffu, /* counter_mask */
#endif
32768, /* frequency */
"AT91RM9200 timer", /* name */
0 /* quality */
};
static int
at91st_probe(device_t dev)
{
device_set_desc(dev, "ST");
return (0);
}
static int
at91st_attach(device_t dev)
{
struct at91_softc *sc = device_get_softc(device_get_parent(dev));
timer_softc = device_get_softc(dev);
timer_softc->sc_st = sc->sc_st;
timer_softc->dev = dev;
if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_ST_BASE,
AT91RM92_ST_SIZE, &timer_softc->sc_sh) != 0)
panic("couldn't subregion timer registers");
/*
* Real time counter increments every clock cycle, need to set before
* initializing clocks so that DELAY works.
*/
WR4(ST_RTMR, 1);
/* Disable all interrupts */
WR4(ST_IDR, 0xffffffff);
return (0);
}
static device_method_t at91st_methods[] = {
DEVMETHOD(device_probe, at91st_probe),
DEVMETHOD(device_attach, at91st_attach),
{0, 0},
};
static driver_t at91st_driver = {
"at91_st",
at91st_methods,
sizeof(struct at91st_softc),
};
static devclass_t at91st_devclass;
DRIVER_MODULE(at91_st, atmelarm, at91st_driver, at91st_devclass, 0, 0);
#ifdef SKYEYE_WORKAROUNDS
static unsigned long tot_count = 0;
#endif
static unsigned
at91st_get_timecount(struct timecounter *tc)
{
#ifdef SKYEYE_WORKAROUNDS
return (tot_count);
#else
return (st_crtr());
#endif
}
static void
clock_intr(void *arg)
{
struct trapframe *fp = arg;
/* The interrupt is shared, so we have to make sure it's for us. */
if (RD4(ST_SR) & ST_SR_PITS) {
#ifdef SKYEYE_WORKAROUNDS
tot_count += 32768 / hz;
#endif
hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
}
}
void
cpu_initclocks(void)
{
int rel_value;
struct resource *irq;
int rid = 0;
void *ih;
device_t dev = timer_softc->dev;
if (32768 % hz) {
printf("Cannot get %d Hz clock; using 128Hz\n", hz);
hz = 128;
}
rel_value = 32768 / hz;
/* Disable all interrupts. */
WR4(ST_IDR, 0xffffffff);
/* The system timer shares the system irq (1) */
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1,
RF_ACTIVE | RF_SHAREABLE);
if (!irq)
panic("Unable to allocate irq for the system timer");
else
bus_setup_intr(dev, irq, INTR_TYPE_CLK | INTR_FAST,
clock_intr, NULL, &ih);
WR4(ST_PIMR, rel_value);
/* Enable PITS interrupts. */
WR4(ST_IER, ST_SR_PITS);
tc_init(&at91st_timecounter);
}
void
DELAY(int n)
{
uint32_t start, end, cur;
start = st_crtr();
n = (n * 1000) / 32768;
if (n <= 0)
n = 1;
end = (start + n) & ST_CRTR_MASK;
cur = start;
if (start > end) {
while (cur >= start || cur < end)
cur = st_crtr();
} else {
while (cur < end)
cur = st_crtr();
}
}
void
cpu_reset(void)
{
/*
* Reset the CPU by programmig the watchdog timer to reset the
* CPU after 128 'slow' clocks, or about ~4ms. Loop until
* the reset happens for safety.
*/
WR4(ST_WDMR, ST_WDMR_RSTEN | 2);
WR4(ST_CR, ST_CR_WDRST);
while (1)
continue;
}
void
cpu_startprofclock(void)
{
}
void
cpu_stopprofclock(void)
{
}

View File

@ -0,0 +1,109 @@
/*-
* Copyright (c) 2005 Olivier Houchard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
#include <arm/at91/at91rm92reg.h>
#include "uart_if.h"
static int usart_at91rm92_probe(device_t dev);
extern struct uart_class at91_usart_class;
static device_method_t usart_at91rm92_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, usart_at91rm92_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t usart_at91rm92_driver = {
uart_driver_name,
usart_at91rm92_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
usart_at91rm92_probe(device_t dev)
{
struct uart_softc *sc;
sc = device_get_softc(dev);
switch (device_get_unit(dev))
{
case 0:
#ifdef SKYEYE_WORKAROUNDS
device_set_desc(dev, "USART0");
#else
device_set_desc(dev, "DBGU");
#endif
/*
* Setting sc_sysdev makes this device a 'system device' and
* indirectly makes it the system console.
*/
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
break;
case 1:
device_set_desc(dev, "USART0");
break;
case 2:
device_set_desc(dev, "USART1");
break;
case 3:
device_set_desc(dev, "USART2");
break;
case 4:
device_set_desc(dev, "USART3");
break;
}
sc->sc_class = &at91_usart_class;
return (uart_bus_probe(dev, 0, 0, 0, device_get_unit(dev)));
}
DRIVER_MODULE(uart, atmelarm, usart_at91rm92_driver, uart_devclass, 0, 0);

View File

@ -0,0 +1,83 @@
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <arm/at91/at91rm92reg.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
extern struct uart_ops at91_usart_ops;
extern struct bus_space at91_bs_tag;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
di->ops = at91_usart_ops;
di->bas.chan = 0;
di->bas.bst = &at91_bs_tag;
/*
* XXX: Not pretty, but will work because we map VA == PA early
* for the last 1MB of memory.
*/
#ifdef SKYEYE_WORKAROUNDS
di->bas.bsh = AT91RM92_BASE + AT91RM92_USART0_BASE;
di->baudrate = 38400;
#else
di->bas.bsh = AT91RM92_BASE + AT91RM92_SYS_BASE + DBGU;
di->baudrate = 115200;
#endif
di->bas.regshft = 0;
di->bas.rclk = 0;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = &at91_bs_tag;
uart_bus_space_mem = NULL;
/* Check the environment for overrides */
if (uart_getenv(devtype, di) == 0)
return (0);
return (0);
}

View File

@ -0,0 +1,490 @@
/*-
* Copyright (c) 2005 M. Warner Losh
* Copyright (c) 2005 Olivier Houchard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/tty.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <arm/at91/at91rm92reg.h>
#include <arm/at91/at91_usartreg.h>
#include <arm/at91/at91_pdcreg.h>
#include "uart_if.h"
/*
* High-level UART interface.
*/
struct at91_usart_softc {
struct uart_softc base;
bus_dma_tag_t dmatag; /* bus dma tag for mbufs */
bus_dmamap_t tx_map;
bus_dmamap_t rx_map;
};
#define DEFAULT_RCLK AT91C_MASTER_CLOCK
#define USART_BUFFER_SIZE 128
#define RD4(bas, reg) \
bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
#define WR4(bas, reg, value) \
bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
#define SIGCHG(c, i, s, d) \
do { \
if (c) { \
i |= (i & s) ? s : s | d; \
} else { \
i = (i & s) ? (i & ~s) | d : i; \
} \
} while (0);
/*
* Low-level UART interface.
*/
static int at91_usart_probe(struct uart_bas *bas);
static void at91_usart_init(struct uart_bas *bas, int, int, int, int);
static void at91_usart_term(struct uart_bas *bas);
static void at91_usart_putc(struct uart_bas *bas, int);
static int at91_usart_poll(struct uart_bas *bas);
static int at91_usart_getc(struct uart_bas *bas, struct mtx *mtx);
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
at91_usart_param(struct uart_bas *bas, int baudrate, int databits,
int stopbits, int parity)
{
uint32_t mr;
/*
* Assume 3-write RS-232 configuration.
* XXX Not sure how uart will present the other modes to us, so
* XXX they are unimplemented. maybe ioctl?
*/
mr = USART_MR_MODE_NORMAL;
mr |= USART_MR_USCLKS_MCK; /* Assume MCK */
/*
* Or in the databits requested
*/
if (databits < 9)
mr &= ~USART_MR_MODE9;
switch (databits) {
case 5:
mr |= USART_MR_CHRL_5BITS;
break;
case 6:
mr |= USART_MR_CHRL_6BITS;
break;
case 7:
mr |= USART_MR_CHRL_7BITS;
break;
case 8:
mr |= USART_MR_CHRL_8BITS;
break;
case 9:
mr |= USART_MR_CHRL_8BITS | USART_MR_MODE9;
break;
default:
return (EINVAL);
}
/*
* Or in the parity
*/
switch (parity) {
case UART_PARITY_NONE:
mr |= USART_MR_PAR_NONE;
break;
case UART_PARITY_ODD:
mr |= USART_MR_PAR_ODD;
break;
case UART_PARITY_EVEN:
mr |= USART_MR_PAR_EVEN;
break;
case UART_PARITY_MARK:
mr |= USART_MR_PAR_MARK;
break;
case UART_PARITY_SPACE:
mr |= USART_MR_PAR_SPACE;
break;
default:
return (EINVAL);
}
/*
* Or in the stop bits. Note: The hardware supports
* 1.5 stop bits in async mode, but there's no way to
* specify that AFAICT.
*/
if (stopbits > 1)
mr |= USART_MR_NBSTOP_2;
else
mr |= USART_MR_NBSTOP_2;
/* else if (stopbits == 1.5)
mr |= USART_MR_NBSTOP_1_5; */
/*
* We want normal plumbing mode too, none of this fancy
* loopback or echo mode.
*/
mr |= USART_MR_CHMODE_NORMAL;
mr &= ~USART_MR_MSBF; /* lsb first */
mr &= ~USART_MR_CKLO_SCK; /* Don't drive SCK */
/* XXX Need to take possible synchronous mode into account */
return (0);
}
struct uart_ops at91_usart_ops = {
.probe = at91_usart_probe,
.init = at91_usart_init,
.term = at91_usart_term,
.putc = at91_usart_putc,
.poll = at91_usart_poll,
.getc = at91_usart_getc,
};
static int
at91_usart_probe(struct uart_bas *bas)
{
/* We know that this is always here */
return (0);
}
/*
* Initialize this device (I think as the console)
*/
static void
at91_usart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
{
int cr;
at91_usart_param(bas, baudrate, databits, stopbits, parity);
/* Turn on rx and tx */
cr = USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX;
WR4(bas, USART_CR, cr);
WR4(bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN);
WR4(bas, USART_IER, USART_CSR_TIMEOUT |
USART_CSR_TXRDY | USART_CSR_RXRDY |
USART_CSR_RXBRK | USART_CSR_ENDRX | USART_CSR_ENDTX);
/* Set the receive timeout to be 1.5 character times. */
WR4(bas, USART_RTOR, 12);
}
/*
* Free resources now that we're no longer the console. This appears to
* be never called, and I'm unsure quite what to do if I am called.
*/
static void
at91_usart_term(struct uart_bas *bas)
{
/* XXX */
}
/*
* Put a character of console output (so we do it here polling rather than
* interrutp driven).
*/
static void
at91_usart_putc(struct uart_bas *bas, int c)
{
while (!(RD4(bas, USART_CSR) &
USART_CSR_TXRDY));
WR4(bas, USART_THR, c);
}
/*
* Poll for a character available
*/
static int
at91_usart_poll(struct uart_bas *bas)
{
if (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY))
return (-1);
return (RD4(bas, USART_RHR) & 0xff);
}
/*
* Block waiting for a character.
*/
static int
at91_usart_getc(struct uart_bas *bas, struct mtx *mtx)
{
int c;
while (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY))
;
c = RD4(bas, USART_RHR);
c &= 0xff;
return (c);
}
static int at91_usart_bus_probe(struct uart_softc *sc);
static int at91_usart_bus_attach(struct uart_softc *sc);
static int at91_usart_bus_flush(struct uart_softc *, int);
static int at91_usart_bus_getsig(struct uart_softc *);
static int at91_usart_bus_ioctl(struct uart_softc *, int, intptr_t);
static int at91_usart_bus_ipend(struct uart_softc *);
static int at91_usart_bus_param(struct uart_softc *, int, int, int, int);
static int at91_usart_bus_receive(struct uart_softc *);
static int at91_usart_bus_setsig(struct uart_softc *, int);
static int at91_usart_bus_transmit(struct uart_softc *);
static kobj_method_t at91_usart_methods[] = {
KOBJMETHOD(uart_probe, at91_usart_bus_probe),
KOBJMETHOD(uart_attach, at91_usart_bus_attach),
KOBJMETHOD(uart_flush, at91_usart_bus_flush),
KOBJMETHOD(uart_getsig, at91_usart_bus_getsig),
KOBJMETHOD(uart_ioctl, at91_usart_bus_ioctl),
KOBJMETHOD(uart_ipend, at91_usart_bus_ipend),
KOBJMETHOD(uart_param, at91_usart_bus_param),
KOBJMETHOD(uart_receive, at91_usart_bus_receive),
KOBJMETHOD(uart_setsig, at91_usart_bus_setsig),
KOBJMETHOD(uart_transmit, at91_usart_bus_transmit),
{ 0, 0 }
};
int
at91_usart_bus_probe(struct uart_softc *sc)
{
return (0);
}
static int
at91_usart_bus_attach(struct uart_softc *sc)
{
int err;
struct at91_usart_softc *atsc;
atsc = (struct at91_usart_softc *)sc;
sc->sc_txfifosz = USART_BUFFER_SIZE;
sc->sc_rxfifosz = USART_BUFFER_SIZE;
sc->sc_hwiflow = 0;
/*
* Allocate DMA tags and maps
*/
err = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL, USART_BUFFER_SIZE, 1,
USART_BUFFER_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL, &atsc->dmatag);
if (err != 0)
goto errout;
err = bus_dmamap_create(atsc->dmatag, 0, &atsc->tx_map);
if (err != 0)
goto errout;
err = bus_dmamap_create(atsc->dmatag, 0, &atsc->rx_map);
if (err != 0)
goto errout;
errout:;
// XXX bad
return (err);
}
#ifndef SKYEYE_WORKAROUNDS
static void
at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
if (error != 0)
return;
*(bus_addr_t *)arg = segs[0].ds_addr;
}
#endif
static int
at91_usart_bus_transmit(struct uart_softc *sc)
{
#ifndef SKYEYE_WORKAROUNDS
bus_addr_t addr;
#endif
struct at91_usart_softc *atsc;
atsc = (struct at91_usart_softc *)sc;
#ifndef SKYEYE_WORKAROUNDS
if (bus_dmamap_load(atsc->dmatag, atsc->tx_map, sc->sc_txbuf,
sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0)
return (EAGAIN);
bus_dmamap_sync(atsc->dmatag, atsc->tx_map, BUS_DMASYNC_PREWRITE);
#endif
uart_lock(sc->sc_hwmtx);
sc->sc_txbusy = 1;
#ifndef SKYEYE_WORKAROUNDS
/*
* Setup the PDC to transfer the data and interrupt us when it
* is done. We've already requested the interrupt.
*/
WR4(&sc->sc_bas, PDC_TPR, addr);
WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz);
WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN);
uart_unlock(sc->sc_hwmtx);
#else
for (int i = 0; i < sc->sc_txdatasz; i++)
at91_usart_putc(&sc->sc_bas, sc->sc_txbuf[i]);
/*
* XXX: Gross hack : Skyeye doesn't raise an interrupt once the
* transfer is done, so simulate it.
*/
WR4(&sc->sc_bas, USART_IER, USART_CSR_TXRDY);
#endif
return (0);
}
static int
at91_usart_bus_setsig(struct uart_softc *sc, int sig)
{
uint32_t new, old, cr;
struct uart_bas *bas;
do {
old = sc->sc_hwsig;
new = old;
if (sig & SER_DDTR)
SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
if (sig & SER_DRTS)
SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
cr = RD4(bas, USART_CR);
cr &= ~(USART_CR_DTREN | USART_CR_DTRDIS | USART_CR_RTSEN |
USART_CR_RTSDIS);
if (new & SER_DTR)
cr |= USART_CR_DTREN;
else
cr |= USART_CR_DTRDIS;
if (new & SER_RTS)
cr |= USART_CR_RTSEN;
else
cr |= USART_CR_RTSDIS;
WR4(bas, USART_CR, cr);
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
at91_usart_bus_receive(struct uart_softc *sc)
{
uart_lock(sc->sc_hwmtx);
uart_rx_put(sc, at91_usart_getc(&sc->sc_bas, NULL));
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
at91_usart_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
return (at91_usart_param(&sc->sc_bas, baudrate, databits, stopbits,
parity));
}
static int
at91_usart_bus_ipend(struct uart_softc *sc)
{
int csr = RD4(&sc->sc_bas, USART_CSR);
int ipend = 0;
struct at91_usart_softc *atsc;
atsc = (struct at91_usart_softc *)sc;
if (csr & USART_CSR_ENDTX) {
bus_dmamap_sync(atsc->dmatag, atsc->tx_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(atsc->dmatag, atsc->tx_map);
}
uart_lock(sc->sc_hwmtx);
if (csr & USART_CSR_TXRDY && sc->sc_txbusy)
ipend |= SER_INT_TXIDLE;
if (csr & USART_CSR_ENDTX && sc->sc_txbusy)
ipend |= SER_INT_TXIDLE;
if (csr & (USART_CSR_RXRDY /* | USART_CSR_ENDRX | USART_CSR_TIMEOUT */))
ipend |= SER_INT_RXREADY;
if (csr & USART_CSR_RXBRK) {
unsigned int cr = USART_CR_RSTSTA;
ipend |= SER_INT_BREAK;
WR4(&sc->sc_bas, USART_CR, cr);
}
uart_unlock(sc->sc_hwmtx);
return (ipend);
}
static int
at91_usart_bus_flush(struct uart_softc *sc, int what)
{
return (0);
}
static int
at91_usart_bus_getsig(struct uart_softc *sc)
{
uint32_t new, sig;
uint8_t csr;
uart_lock(sc->sc_hwmtx);
csr = RD4(&sc->sc_bas, USART_CSR);
sig = 0;
if (csr & USART_CSR_CTS)
sig |= SER_CTS;
if (csr & USART_CSR_DCD)
sig |= SER_DCD;
if (csr & USART_CSR_DSR)
sig |= SER_DSR;
if (csr & USART_CSR_RI)
sig |= SER_RI;
new = sig & ~SER_MASK_DELTA;
sc->sc_hwsig = new;
uart_unlock(sc->sc_hwmtx);
return (sig);
}
static int
at91_usart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
return (EINVAL);
}
struct uart_class at91_usart_class = {
"at91_usart class",
at91_usart_methods,
sizeof(struct at91_usart_softc),
.uc_range = 8,
.uc_rclk = DEFAULT_RCLK
};

View File

@ -0,0 +1,13 @@
# $FreeBSD$
PROG= cdboot
STRIP=
BINMODE=${NOBINMODE}
NO_MAN=
SRCS= ${PROG}.s
ORG= 0x0000
LDFLAGS=-N -e start -Ttext ${ORG} -Wl,-S,--oformat,binary
.include <bsd.prog.mk>

View File

@ -0,0 +1,811 @@
#
# Copyright (c) 2006 TAKAHASHI Yoshihiro <nyan@FreeBSD.org>
# Copyright (c) 2001 John Baldwin <jhb@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# Basically, we first create a set of boot arguments to pass to the loaded
# binary. Then we attempt to load /boot/loader from the CD we were booted
# off of.
#
#
# Memory locations.
#
.set STACK_OFF,0x6000 # Stack offset
.set LOAD_SEG,0x0700 # Load segment
.set LOAD_SIZE,2048 # Load size
.set DAUA,0x0584 # DA/UA
.set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
.set MEM_ARG,0x900 # Arguments at start
.set MEM_ARG_BTX,0xa100 # Where we move them to so the
# BTX client can see them
.set MEM_ARG_SIZE,0x18 # Size of the arguments
.set MEM_BTX_ADDRESS,0x9000 # where BTX lives
.set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
.set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
.set MEM_BTX_CLIENT,0xa000 # where BTX clients live
#
# PC98 machine type from sys/pc98/pc98/pc98_machdep.h
#
.set MEM_SYS, 0xa100 # System common area segment
.set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
.set EPSON_ID, 0x0624 # EPSON machine id
.set M_NEC_PC98, 0x0001
.set M_EPSON_PC98, 0x0002
.set M_NOT_H98, 0x0010
.set M_H98, 0x0020
.set M_NOTE, 0x0040
.set M_NORMAL, 0x1000
.set M_8M, 0x8000
#
# Signature Constants
#
.set SIG1_OFF,0x1fe # Signature offset
.set SIG2_OFF,0x7fe # Signature offset
#
# a.out header fields
#
.set AOUT_TEXT,0x04 # text segment size
.set AOUT_DATA,0x08 # data segment size
.set AOUT_BSS,0x0c # zero'd BSS size
.set AOUT_SYMBOLS,0x10 # symbol table
.set AOUT_ENTRY,0x14 # entry point
.set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
#
# Flags for kargs->bootflags
#
.set KARGS_FLAGS_CD,0x1 # flag to indicate booting from
# CD loader
#
# Segment selectors.
#
.set SEL_SDATA,0x8 # Supervisor data
.set SEL_RDATA,0x10 # Real mode data
.set SEL_SCODE,0x18 # PM-32 code
.set SEL_SCODE16,0x20 # PM-16 code
#
# BTX constants
#
.set INT_SYS,0x30 # BTX syscall interrupt
#
# Constants for reading from the CD.
#
.set ERROR_TIMEOUT,0x90 # BIOS timeout on read
.set NUM_RETRIES,3 # Num times to retry
.set SECTOR_SIZE,0x800 # size of a sector
.set SECTOR_SHIFT,11 # number of place to shift
.set BUFFER_LEN,0x100 # number of sectors in buffer
.set MAX_READ,0xf800 # max we can read at a time
.set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
.set MEM_READ_BUFFER,0x9000 # buffer to read from CD
.set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
.set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
.set VOLDESC_LBA,0x10 # LBA of vol descriptor
.set VD_PRIMARY,1 # Primary VD
.set VD_END,255 # VD Terminator
.set VD_ROOTDIR,156 # Offset of Root Dir Record
.set DIR_LEN,0 # Offset of Dir Record length
.set DIR_EA_LEN,1 # Offset of EA length
.set DIR_EXTENT,2 # Offset of 64-bit LBA
.set DIR_SIZE,10 # Offset of 64-bit length
.set DIR_NAMELEN,32 # Offset of 8-bit name len
.set DIR_NAME,33 # Offset of dir name
#
# Program start.
#
.code16
.globl start
start: jmp main
.org 4
.ascii "IPL1 "
main: cld
/* Setup the stack */
xor %ax,%ax
mov %ax,%ss
mov $STACK_OFF,%sp
push %ecx
/* Setup graphic screen */
mov $0x42,%ah # 640x400
mov $0xc0,%ch
int $0x18
mov $0x40,%ah # graph on
int $0x18
/* Setup text screen */
mov $0x0a00,%ax # 80x25
int $0x18
mov $0x0c,%ah # text on
int $0x18
mov $0x13,%ah # cursor home
xor %dx,%dx
int $0x18
mov $0x11,%ah # cursor on
int $0x18
/* Setup keyboard */
mov $0x03,%ah
int $0x18
/* Transfer PC-9801 system common area */
xor %ax,%ax
mov %ax,%si
mov %ax,%ds
mov %ax,%di
mov $MEM_SYS,%ax
mov %ax,%es
mov $0x0600,%cx
rep
movsb
/* Transfer EPSON machine type */
mov $0xfd00,%ax
mov %ax,%ds
mov (0x804),%eax
and $0x00ffffff,%eax
mov %eax,%es:(EPSON_ID)
/* Set machine type to PC98_SYSTEM_PARAMETER */
call machine_check
/* Load cdboot */
xor %ax,%ax
mov %ax,%ds
mov $0x06,%ah /* Read data */
mov (DAUA),%al /* Read drive */
pop %ecx /* cylinder */
xor %dx,%dx /* head / sector */
mov $LOAD_SEG,%bx /* Load address */
mov %bx,%es
xor %bp,%bp
mov $LOAD_SIZE,%bx /* Load size */
int $0x1b
mov $msg_readerr,%si
jc error
/* Jump to cdboot */
ljmp $LOAD_SEG,$cdboot
#
# Set machine type to PC98_SYSTEM_PARAMETER.
#
machine_check: xor %edx,%edx
mov %dx,%ds
mov $MEM_SYS,%ax
mov %ax,%es
/* Wait V-SYNC */
vsync.1: inb $0x60,%al
test $0x20,%al
jnz vsync.1
vsync.2: inb $0x60,%al
test $0x20,%al
jz vsync.2
/* ANK 'A' font */
xor %al,%al
outb %al,$0xa1
mov $0x41,%al
outb %al,$0xa3
/* Get 'A' font from CG window */
push %ds
mov $0xa400,%ax
mov %ax,%ds
xor %eax,%eax
xor %bx,%bx
mov $4,%cx
font.1: add (%bx),%eax
add $4,%bx
loop font.1
pop %ds
cmp $0x6efc58fc,%eax
jnz m_epson
m_pc98: or $M_NEC_PC98,%edx
mov $0x0458,%bx
mov (%bx),%al
test $0x80,%al
jz m_not_h98
or $M_H98,%edx
jmp 1f
m_epson: or $M_EPSON_PC98,%edx
m_not_h98: or $M_NOT_H98,%edx
1: inb $0x42,%al
test $0x20,%al
jz 1f
or $M_8M,%edx
1: mov $0x0400,%bx
mov (%bx),%al
test $0x80,%al
jz 1f
or $M_NOTE,%edx
1: mov $PC98_MACHINE_TYPE,%bx
mov %edx,%es:(%bx)
ret
#
# Print out the error message at [SI], wait for a keypress, and then
# reboot the machine.
#
error: call putstr
mov $msg_keypress,%si
call putstr
xor %ax,%ax # Get keypress
int $0x18
xor %ax,%ax # CPU reset
outb %al,$0xf0
halt: hlt
jmp halt # Spin
#
# Display a null-terminated string at [SI].
#
# Trashes: AX, BX, CX, DX, SI, DI
#
putstr: push %ds
push %es
mov %cs,%ax
mov %ax,%ds
mov $0xa000,%ax
mov %ax,%es
mov cursor,%di
mov $0x00e1,%bx # Attribute
mov $160,%cx
putstr.0: lodsb
testb %al,%al
jz putstr.done
cmp $0x0d,%al
jz putstr.cr
cmp $0x0a,%al
jz putstr.lf
mov %bl,%es:0x2000(%di)
stosb
inc %di
jmp putstr.move
putstr.cr: xor %dx,%dx
mov %di,%ax
div %cx
sub %dx,%di
jmp putstr.move
putstr.lf: add %cx,%di
putstr.move: mov %di,%dx
mov $0x13,%ah # Move cursor
int $0x18
jmp putstr.0
putstr.done: mov %di,cursor
pop %es
pop %ds
ret
#
# Display a single char at [AL], but don't move a cursor.
#
putc: push %es
push %di
push %bx
mov $0xa000,%bx
mov %bx,%es
mov cursor,%di
mov $0xe1,%bl # Attribute
mov %bl,%es:0x2000(%di)
stosb
pop %bx
pop %di
pop %es
ret
msg_readerr: .asciz "Read Error\r\n"
msg_keypress: .asciz "\r\nPress any key to reboot\r\n"
/* Boot signature */
.org SIG1_OFF,0x90
.word 0xaa55 # Magic number
#
# cdboot
#
cdboot: mov %cs,%ax
mov %ax,%ds
xor %ax,%ax
mov %ax,%es
mov %es:(DAUA),%al # Save BIOS boot device
mov %al,drive
mov %cx,cylinder # Save BIOS boot cylinder
mov $msg_welcome,%si # %ds:(%si) -> welcome message
call putstr # display the welcome message
#
# Setup the arguments that the loader is expecting from boot[12]
#
mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
call putstr # display the message
mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
mov %bx,%di # %es:(%di) -> boot args
xor %eax,%eax # zero %eax
mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
# dwords
rep # Clear the arguments
stosl # to zero
mov drive,%dl # Store BIOS boot device
mov %dl,%es:0x4(%bx) # in kargs->bootdev
or $KARGS_FLAGS_CD,%es:0x8(%bx) # kargs->bootflags |=
# KARGS_FLAGS_CD
#
# Load Volume Descriptor
#
mov $VOLDESC_LBA,%eax # Set LBA of first VD
load_vd: push %eax # Save %eax
mov $1,%dh # One sector
mov $MEM_VOLDESC,%ebx # Destination
call read # Read it in
cmpb $VD_PRIMARY,%es:(%bx) # Primary VD?
je have_vd # Yes
pop %eax # Prepare to
inc %eax # try next
cmpb $VD_END,%es:(%bx) # Last VD?
jne load_vd # No, read next
mov $msg_novd,%si # No VD
jmp error # Halt
have_vd: # Have Primary VD
#
# Try to look up the loader binary using the paths in the loader_paths
# array.
#
mov $loader_paths,%si # Point to start of array
lookup_path: push %si # Save file name pointer
call lookup # Try to find file
pop %di # Restore file name pointer
jnc lookup_found # Found this file
push %es
mov %cs,%ax
mov %ax,%es
xor %al,%al # Look for next
mov $0xffff,%cx # path name by
repnz # scanning for
scasb # nul char
pop %es
mov %di,%si # Point %si at next path
mov (%si),%al # Get first char of next path
or %al,%al # Is it double nul?
jnz lookup_path # No, try it.
mov $msg_failed,%si # Failed message
jmp error # Halt
lookup_found: # Found a loader file
#
# Load the binary into the buffer. Due to real mode addressing limitations
# we have to read it in in 64k chunks.
#
mov %es:DIR_SIZE(%bx),%eax # Read file length
add $SECTOR_SIZE-1,%eax # Convert length to sectors
shr $SECTOR_SHIFT,%eax
cmp $BUFFER_LEN,%eax
jbe load_sizeok
mov $msg_load2big,%si # Error message
jmp error
load_sizeok: movzbw %al,%cx # Num sectors to read
mov %es:DIR_EXTENT(%bx),%eax # Load extent
xor %edx,%edx
mov %es:DIR_EA_LEN(%bx),%dl
add %edx,%eax # Skip extended
mov $MEM_READ_BUFFER,%ebx # Read into the buffer
load_loop: mov %cl,%dh
cmp $MAX_READ_SEC,%cl # Truncate to max read size
jbe load_notrunc
mov $MAX_READ_SEC,%dh
load_notrunc: sub %dh,%cl # Update count
push %eax # Save
call read # Read it in
pop %eax # Restore
add $MAX_READ_SEC,%eax # Update LBA
add $MAX_READ,%ebx # Update dest addr
jcxz load_done # Done?
jmp load_loop # Keep going
load_done:
#
# Turn on the A20 address line
#
xor %ax,%ax # Turn A20 on
outb %al,$0xf2
mov $0x02,%al
outb %al,$0xf6
#
# Relocate the loader and BTX using a very lazy protected mode
#
mov $msg_relocate,%si # Display the
call putstr # relocation message
mov %es:(MEM_READ_BUFFER+AOUT_ENTRY),%edi # %edi is the destination
mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
# the start of the text
# segment
mov %es:(MEM_READ_BUFFER+AOUT_TEXT),%ecx # %ecx = length of the text
# segment
push %edi # Save entry point for later
lgdt gdtdesc # setup our own gdt
cli # turn off interrupts
mov %cr0,%eax # Turn on
or $0x1,%al # protected
mov %eax,%cr0 # mode
ljmp $SEL_SCODE,$pm_start # long jump to clear the
# instruction pre-fetch queue
.code32
pm_start: mov $SEL_SDATA,%ax # Initialize
mov %ax,%ds # %ds and
mov %ax,%es # %es to a flat selector
rep # Relocate the
movsb # text segment
add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
rep # Relocate the
movsb # data segment
mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
xor %eax,%eax # zero %eax
add $3,%cl # round %ecx up to
shr $2,%ecx # a multiple of 4
rep # zero the
stosl # bss
mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
rep # Relocate
movsb # BTX
ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
.code16
pm_16: mov $SEL_RDATA,%ax # Initialize
mov %ax,%ds # %ds and
mov %ax,%es # %es to a real mode selector
mov %cr0,%eax # Turn off
and $~0x1,%al # protected
mov %eax,%cr0 # mode
ljmp $LOAD_SEG,$pm_end # Long jump to clear the
# instruction pre-fetch queue
pm_end: sti # Turn interrupts back on now
#
# Copy the BTX client to MEM_BTX_CLIENT
#
mov %cs,%ax
mov %ax,%ds
xor %ax,%ax
mov %ax,%es
mov $MEM_BTX_CLIENT,%di # Prepare to relocate
mov $btx_client,%si # the simple btx client
mov $(btx_client_end-btx_client),%cx # length of btx client
rep # Relocate the
movsb # simple BTX client
#
# Copy the boot[12] args to where the BTX client can see them
#
xor %ax,%ax
mov %ax,%ds
mov $MEM_ARG,%si # where the args are at now
mov $MEM_ARG_BTX,%di # where the args are moving to
mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
rep # Relocate
movsl # the words
#
# Save the entry point so the client can get to it later on
#
pop %eax # Restore saved entry point
stosl # and add it to the end of
# the arguments
#
# Now we just start up BTX and let it do the rest
#
mov $msg_jump,%si # Display the
call putstr # jump message
ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
#
# Lookup the file in the path at [SI] from the root directory.
#
# Trashes: All but BX
# Returns: CF = 0 (success), BX = pointer to record
# CF = 1 (not found)
#
lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
push %bx
push %si
mov $msg_lookup,%si # Display lookup message
call putstr
pop %si
push %si
call putstr
mov $msg_lookup2,%si
call putstr
pop %si
pop %bx
lookup_dir: lodsb # Get first char of path
cmp $0,%al # Are we done?
je lookup_done # Yes
cmp $'/',%al # Skip path separator.
je lookup_dir
dec %si # Undo lodsb side effect
call find_file # Lookup first path item
jnc lookup_dir # Try next component
mov $msg_lookupfail,%si # Not found message
push %bx
call putstr
pop %bx
stc # Set carry
ret
lookup_done: mov $msg_lookupok,%si # Success message
push %bx
call putstr
pop %bx
clc # Clear carry
ret
#
# Lookup file at [SI] in directory whose record is at [BX].
#
# Trashes: All but returns
# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
# CF = 1 (not found), SI = preserved
#
find_file: mov %es:DIR_EXTENT(%bx),%eax # Load extent
xor %edx,%edx
mov %es:DIR_EA_LEN(%bx),%dl
add %edx,%eax # Skip extended attributes
mov %eax,rec_lba # Save LBA
mov %es:DIR_SIZE(%bx),%eax # Save size
mov %eax,rec_size
xor %cl,%cl # Zero length
push %si # Save
ff.namelen: inc %cl # Update length
lodsb # Read char
cmp $0,%al # Nul?
je ff.namedone # Yes
cmp $'/',%al # Path separator?
jnz ff.namelen # No, keep going
ff.namedone: dec %cl # Adjust length and save
mov %cl,name_len
pop %si # Restore
ff.load: mov rec_lba,%eax # Load LBA
mov $MEM_DIR,%ebx # Address buffer
mov $1,%dh # One sector
call read # Read directory block
incl rec_lba # Update LBA to next block
ff.scan: mov %ebx,%edx # Check for EOF
sub $MEM_DIR,%edx
cmp %edx,rec_size
ja ff.scan.1
stc # EOF reached
ret
ff.scan.1: cmpb $0,%es:DIR_LEN(%bx) # Last record in block?
je ff.nextblock
push %si # Save
movzbw %es:DIR_NAMELEN(%bx),%si # Find end of string
ff.checkver: cmpb $'0',%es:DIR_NAME-1(%bx,%si) # Less than '0'?
jb ff.checkver.1
cmpb $'9',%es:DIR_NAME-1(%bx,%si) # Greater than '9'?
ja ff.checkver.1
dec %si # Next char
jnz ff.checkver
jmp ff.checklen # All numbers in name, so
# no version
ff.checkver.1: movzbw %es:DIR_NAMELEN(%bx),%cx
cmp %cx,%si # Did we find any digits?
je ff.checkdot # No
cmpb $';',%es:DIR_NAME-1(%bx,%si) # Check for semicolon
jne ff.checkver.2
dec %si # Skip semicolon
mov %si,%cx
mov %cl,%es:DIR_NAMELEN(%bx) # Adjust length
jmp ff.checkdot
ff.checkver.2: mov %cx,%si # Restore %si to end of string
ff.checkdot: cmpb $'.',%es:DIR_NAME-1(%bx,%si) # Trailing dot?
jne ff.checklen # No
decb %es:DIR_NAMELEN(%bx) # Adjust length
ff.checklen: pop %si # Restore
movzbw name_len,%cx # Load length of name
cmp %cl,%es:DIR_NAMELEN(%bx) # Does length match?
je ff.checkname # Yes, check name
ff.nextrec: add %es:DIR_LEN(%bx),%bl # Next record
adc $0,%bh
jmp ff.scan
ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
jnc ff.load # If subtract ok, keep going
ret # End of file, so not found
ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
push %si # Save
repe cmpsb # Compare name
je ff.match # We have a winner!
pop %si # Restore
jmp ff.nextrec # Keep looking.
ff.match: add $2,%sp # Discard saved %si
clc # Clear carry
ret
#
# Load DH sectors starting at LBA EAX into [EBX].
#
# Trashes: EAX
#
read: push %es # Save
push %bp
push %dx
push %cx
push %ebx
mov %bx,%bp # Set destination address
and $0x000f,%bp
shr $4,%ebx
mov %bx,%es
xor %bx,%bx # Set read bytes
mov %dh,%bl
shl $SECTOR_SHIFT,%bx # 2048 bytes/sec
mov %ax,%cx # Set LBA
shr $16,%eax
mov %ax,%dx
read.retry: mov $0x06,%ah # BIOS device read
mov drive,%al
and $0x7f,%al
call twiddle # Entertain the user
int $0x1b # Call BIOS
jc read.fail # Worked?
pop %ebx # Restore
pop %cx
pop %dx
pop %bp
pop %es
ret # Return
read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
je read.retry # Yes, Retry.
read.error: mov %ah,%al # Save error
mov $hex_error,%di # Format it
call hex8 # as hex
mov $msg_badread,%si # Display Read error message
jmp error
#
# Output the "twiddle"
#
twiddle: push %ax # Save
push %bx # Save
mov twiddle_index,%al # Load index
mov twiddle_chars,%bx # Address table
inc %al # Next
and $3,%al # char
mov %al,twiddle_index # Save index for next call
xlat # Get char
call putc # Output it
pop %bx # Restore
pop %ax # Restore
ret
#
# Convert AL to hex, saving the result to [EDI].
#
hex8: pushl %eax # Save
shrb $0x4,%al # Do upper
call hex8.1 # 4
popl %eax # Restore
hex8.1: andb $0xf,%al # Get lower 4
cmpb $0xa,%al # Convert
sbbb $0x69,%al # to hex
das # digit
orb $0x20,%al # To lower case
mov %al,(%di) # Save char
inc %di
ret # (Recursive)
#
# BTX client to start btxldr
#
.code32
btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
# %ds:(%esi) -> end
# of boot[12] args
mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
std # Go backwards
push_arg: lodsl # Read argument
push %eax # Push it onto the stack
loop push_arg # Push all of the arguments
cld # In case anyone depends on this
pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
# the loader
push %eax # Emulate a near call
mov $0x1,%eax # 'exec' system call
int $INT_SYS # BTX system call
btx_client_end:
.code16
.p2align 4
#
# Global descriptor table.
#
gdt: .word 0x0,0x0,0x0,0x0 # Null entry
.word 0xffff,0x0000,0x9200,0x00cf # SEL_SDATA
.word 0xffff,0x0000,0x9200,0x0000 # SEL_RDATA
.word 0xffff,LOAD_SEG<<4,0x9a00,0x00cf # SEL_SCODE (32-bit)
.word 0xffff,LOAD_SEG<<4,0x9a00,0x008f # SEL_SCODE16 (16-bit)
gdt.1:
#
# Pseudo-descriptors.
#
gdtdesc: .word gdt.1-gdt-1 # Limit
.long LOAD_SEG<<4 + gdt # Base
#
# BOOT device
#
drive: .byte 0
cylinder: .word 0
#
# State for searching dir
#
rec_lba: .long 0x0 # LBA (adjusted for EA)
rec_size: .long 0x0 # File size
name_len: .byte 0x0 # Length of current name
cursor: .word 0
twiddle_index: .byte 0x0
msg_welcome: .asciz "CD Loader 1.2\r\n\n"
msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
msg_jump: .asciz "Starting the BTX loader\r\n"
msg_badread: .ascii "Read Error: 0x"
hex_error: .ascii "00\r\n"
msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
msg_lookup: .asciz "Looking up "
msg_lookup2: .asciz "... "
msg_lookupok: .asciz "Found\r\n"
msg_lookupfail: .asciz "File not found\r\n"
msg_load2big: .asciz "File too big\r\n"
msg_failed: .asciz "Boot failed\r\n"
twiddle_chars: .ascii "|/-\\"
loader_paths: .asciz "/BOOT.PC98/LOADER"
.asciz "/boot.pc98/loader"
.asciz "/BOOT/LOADER"
.asciz "/boot/loader"
.byte 0
/* Boot signature */
.org SIG2_OFF,0x90
.word 0xaa55 # Magic number

View File

@ -0,0 +1,344 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 2001 John H. Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* BIOS CD device handling for CD's that have been booted off of via no
* emulation booting as defined in the El Torito standard.
*
* Ideas and algorithms from:
*
* - FreeBSD libi386/biosdisk.c
*
*/
#include <stand.h>
#include <sys/param.h>
#include <machine/bootinfo.h>
#include <machine/psl.h>
#include <stdarg.h>
#include <bootstrap.h>
#include <btxv86.h>
#include "libi386.h"
#define BIOSCD_SECSIZE 2048
#define BUFSIZE (1 * BIOSCD_SECSIZE)
#define MAXBCDEV 1
/* Major numbers for devices we frontend for. */
#define ACDMAJOR 117
#define CDMAJOR 15
#ifdef DISK_DEBUG
# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
#else
# define DEBUG(fmt, args...)
#endif
struct specification_packet {
u_char sp_size;
u_char sp_bootmedia;
u_char sp_drive;
u_char sp_controller;
u_int sp_lba;
u_short sp_devicespec;
u_short sp_buffersegment;
u_short sp_loadsegment;
u_short sp_sectorcount;
u_short sp_cylsec;
u_char sp_head;
};
/*
* List of BIOS devices, translation from disk unit number to
* BIOS unit number.
*/
static struct bcinfo {
int bc_unit; /* BIOS unit number */
struct specification_packet bc_sp;
} bcinfo [MAXBCDEV];
static int nbcinfo = 0;
static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
static int bc_init(void);
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
size_t size, char *buf, size_t *rsize);
static int bc_open(struct open_file *f, ...);
static int bc_close(struct open_file *f);
static void bc_print(int verbose);
struct devsw bioscd = {
"cd",
DEVT_CD,
bc_init,
bc_strategy,
bc_open,
bc_close,
noioctl,
bc_print,
NULL
};
/*
* Translate between BIOS device numbers and our private unit numbers.
*/
int
bc_bios2unit(int biosdev)
{
int i;
DEBUG("looking for bios device 0x%x", biosdev);
for (i = 0; i < nbcinfo; i++) {
DEBUG("bc unit %d is BIOS device 0x%x", i, bcinfo[i].bc_unit);
if (bcinfo[i].bc_unit == biosdev)
return(i);
}
return(-1);
}
int
bc_unit2bios(int unit)
{
if ((unit >= 0) && (unit < nbcinfo))
return(bcinfo[unit].bc_unit);
return(-1);
}
/*
* We can't quiz, we have to be told what device to use, so this functoin
* doesn't do anything. Instead, the loader calls bc_add() with the BIOS
* device number to add.
*/
static int
bc_init(void)
{
return (0);
}
int
bc_add(int biosdev)
{
if (nbcinfo >= MAXBCDEV)
return (-1);
bcinfo[nbcinfo].bc_unit = biosdev;
/* SCSI CD-ROM only */
if ((biosdev & 0xf0) != 0xa0)
return (-1);
if ((((uint32_t *)PTOV(0xA1460))[biosdev & 0x0f] & 0x1f) != 5)
return (-1);
printf("BIOS CD is cd%d\n", nbcinfo);
nbcinfo++;
return(0);
}
/*
* Print information about disks
*/
static void
bc_print(int verbose)
{
int i;
char line[80];
for (i = 0; i < nbcinfo; i++) {
sprintf(line, " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
pager_output(line);
}
}
/*
* Attempt to open the disk described by (dev) for use by (f).
*/
static int
bc_open(struct open_file *f, ...)
{
va_list ap;
struct i386_devdesc *dev;
va_start(ap, f);
dev = va_arg(ap, struct i386_devdesc *);
va_end(ap);
if (dev->d_kind.bioscd.unit >= nbcinfo) {
DEBUG("attempt to open nonexistent disk");
return(ENXIO);
}
return(0);
}
static int
bc_close(struct open_file *f)
{
return(0);
}
static int
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
size_t *rsize)
{
struct i386_devdesc *dev;
int unit;
int blks;
#ifdef BD_SUPPORT_FRAGS
char fragbuf[BIOSCD_SECSIZE];
size_t fragsize;
fragsize = size % BIOSCD_SECSIZE;
#else
if (size % BIOSCD_SECSIZE)
return (EINVAL);
#endif
if (rw != F_READ)
return(EROFS);
dev = (struct i386_devdesc *)devdata;
unit = dev->d_kind.bioscd.unit;
blks = size / BIOSCD_SECSIZE;
if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
return (EINVAL);
dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
DEBUG("read %d from %d to %p", blks, dblk, buf);
if (rsize)
*rsize = 0;
if (blks && bc_read(unit, dblk, blks, buf)) {
DEBUG("read error");
return (EIO);
}
#ifdef BD_SUPPORT_FRAGS
DEBUG("bc_strategy: frag read %d from %d+%d to %p",
fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
if (fragsize && bc_read(unit, dblk + blks, 1, fragsize)) {
DEBUG("frag read error");
return(EIO);
}
bcopy(fragbuf, buf + (blks * BIOSCD_SECSIZE), fragsize);
#endif
if (rsize)
*rsize = size;
return (0);
}
static int
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
{
u_int result, retry;
static unsigned short packet[8];
int biosdev;
#ifdef DISK_DEBUG
int error;
#endif
/* Just in case some idiot actually tries to read -1 blocks... */
if (blks < 0)
return (-1);
/* If nothing to do, just return succcess. */
if (blks == 0)
return (0);
biosdev = bc_unit2bios(unit);
/*
* Loop retrying the operation a couple of times. The BIOS
* may also retry.
*/
for (retry = 0; retry < 3; retry++) {
/* If retrying, reset the drive */
if (retry > 0) {
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
v86.eax = 0x0300 | biosdev;
v86int();
}
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
v86.eax = 0x0600 | (biosdev & 0x7f);
v86.ebx = blks * BIOSCD_SECSIZE;
v86.ecx = dblk & 0xffff;
v86.edx = (dblk >> 16) & 0xffff;
v86.ebp = VTOPOFF(dest);
v86.es = VTOPSEG(dest);
v86int();
result = (v86.efl & PSL_C);
if (result == 0)
break;
}
#ifdef DISK_DEBUG
error = (v86.eax >> 8) & 0xff;
#endif
DEBUG("%d sectors from %ld to %p (0x%x) %s", blks, dblk, dest,
VTOP(dest), result ? "failed" : "ok");
DEBUG("unit %d status 0x%x", unit, error);
/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
return(0);
}
/*
* Return a suitable dev_t value for (dev).
*/
int
bc_getdev(struct i386_devdesc *dev)
{
int biosdev, unit, device;
int major;
int rootdev;
unit = dev->d_kind.bioscd.unit;
biosdev = bc_unit2bios(unit);
DEBUG("unit %d BIOS device %d", unit, biosdev);
if (biosdev == -1) /* not a BIOS device */
return(-1);
device = biosdev & 0xf0;
if (device == 0x80)
major = ACDMAJOR;
else if (device == 0xa0)
major = CDMAJOR;
else
return (-1);
unit = 0; /* XXX */
/* XXX: Assume partition 'a'. */
rootdev = MAKEBOOTDEV(major, 0, 0, unit, 0);
DEBUG("dev is 0x%x\n", rootdev);
return(rootdev);
}

View File

@ -0,0 +1,283 @@
/*-
* Copyright (c) 2006 IronPort Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/blist.h>
#include <sys/conf.h>
#include <sys/exec.h>
#include <sys/filedesc.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/socket.h>
#include <sys/vnode.h>
#include <sys/bus.h>
#include <sys/pciio.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/if.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_param.h>
#include <vm/vm_object.h>
#include <vm/swap_pager.h>
#include <machine/bus.h>
#include "opt_compat.h"
#ifdef COMPAT_LINUX32 /* XXX */
#include <machine/../linux32/linux.h>
#else
#include <machine/../linux/linux.h>
#endif
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_util.h>
#include <fs/pseudofs/pseudofs.h>
struct scsi_host_queue {
TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
char *path;
char *name;
};
TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
static int host_number = 0;
static int
atoi(const char *str)
{
return (int)strtol(str, (char **)NULL, 10);
}
/*
* Filler function for proc_name
*/
static int
linsysfs_scsiname(PFS_FILL_ARGS)
{
struct scsi_host_queue *scsi_host;
int index;
if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
index = atoi(&pn->pn_parent->pn_name[4]);
} else {
sbuf_printf(sb, "unknown\n");
return (0);
}
TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
if (index-- == 0) {
sbuf_printf(sb, "%s\n", scsi_host->name);
return (0);
}
}
sbuf_printf(sb, "unknown\n");
return (0);
}
/*
* Filler function for device sym-link
*/
static int
linsysfs_link_scsi_host(PFS_FILL_ARGS)
{
struct scsi_host_queue *scsi_host;
int index;
if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
index = atoi(&pn->pn_parent->pn_name[4]);
} else {
sbuf_printf(sb, "unknown\n");
return (0);
}
TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
if (index-- == 0) {
sbuf_printf(sb, "../../../devices%s", scsi_host->path);
return(0);
}
}
sbuf_printf(sb, "unknown\n");
return (0);
}
#define PCI_DEV "pci"
static int
linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path,
char *prefix)
{
struct scsi_host_queue *scsi_host;
struct pfs_node *sub_dir;
int i, nchildren;
device_t *children, parent;
devclass_t devclass;
const char *name = NULL;
struct pci_devinfo *dinfo;
char *device, *host, *new_path = path;
parent = device_get_parent(dev);
if (parent) {
devclass = device_get_devclass(parent);
if (devclass != NULL)
name = devclass_get_name(devclass);
if (name && strcmp(name, PCI_DEV) == 0) {
dinfo = device_get_ivars(dev);
if (dinfo) {
device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
new_path = malloc(MAXPATHLEN, M_TEMP,
M_WAITOK);
new_path[0] = '\000';
strcpy(new_path, path);
host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
device[0] = '\000';
sprintf(device, "%s:%02x:%02x.%x",
prefix,
dinfo->cfg.bus,
dinfo->cfg.slot,
dinfo->cfg.func);
strcat(new_path, "/");
strcat(new_path, device);
dir = pfs_create_dir(dir, device,
NULL, NULL, 0);
if (dinfo->cfg.baseclass == PCIC_STORAGE) {
/* DJA only make this if needed */
sprintf(host, "host%d", host_number++);
strcat(new_path, "/");
strcat(new_path, host);
sub_dir = pfs_create_dir(dir,
host, NULL, NULL, 0);
scsi_host = malloc(sizeof(
struct scsi_host_queue),
M_DEVBUF, M_NOWAIT);
scsi_host->path = malloc(
strlen(new_path) + 1,
M_DEVBUF, M_NOWAIT);
scsi_host->path[0] = '\000';
bcopy(new_path, scsi_host->path,
strlen(new_path) + 1);
scsi_host->name = "unknown";
sub_dir = pfs_create_dir(scsi, host,
NULL, NULL, 0);
pfs_create_link(sub_dir, "device",
&linsysfs_link_scsi_host,
NULL, NULL, 0);
pfs_create_file(sub_dir, "proc_name",
&linsysfs_scsiname,
NULL, NULL, PFS_RD);
scsi_host->name
= linux_driver_get_name_dev(dev);
TAILQ_INSERT_TAIL(&scsi_host_q,
scsi_host, scsi_host_next);
}
free(device, M_TEMP);
free(host, M_TEMP);
}
}
}
device_get_children(dev, &children, &nchildren);
for (i = 0; i < nchildren; i++) {
if (children[i])
linsysfs_run_bus(children[i], dir, scsi, new_path, prefix);
}
if (new_path != path)
free(new_path, M_TEMP);
return (1);
}
/*
* Constructor
*/
static int
linsysfs_init(PFS_INIT_ARGS)
{
struct pfs_node *root;
struct pfs_node *dir;
struct pfs_node *pci;
struct pfs_node *scsi;
devclass_t devclass;
device_t dev;
TAILQ_INIT(&scsi_host_q);
root = pi->pi_root;
/* /sys/class/... */
scsi = pfs_create_dir(root, "class", NULL, NULL, 0);
scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, 0);
/* /sys/device */
dir = pfs_create_dir(root, "devices", NULL, NULL, 0);
/* /sys/device/pci0000:00 */
pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, 0);
devclass = devclass_find("root");
if (devclass == NULL) {
return (0);
}
dev = devclass_get_device(devclass, 0);
linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000");
return (0);
}
/*
* Destructor
*/
static int
linsysfs_uninit(PFS_INIT_ARGS)
{
struct scsi_host_queue *scsi_host;
TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
free(scsi_host->path, M_TEMP);
free(scsi_host, M_TEMP);
}
return (0);
}
PSEUDOFS(linsysfs, 1);
MODULE_DEPEND(linsysfs, linux, 1, 1, 1);

1095
sys/dev/ipmi/ipmi.c Normal file

File diff suppressed because it is too large Load Diff

90
sys/dev/mfi/mfi_linux.c Normal file
View File

@ -0,0 +1,90 @@
/*-
* Copyright (c) 2006 IronPort Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/file.h>
#include <sys/proc.h>
#if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */
#include <machine/../linux32/linux.h>
#include <machine/../linux32/linux32_proto.h>
#else
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#endif
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_util.h>
/* There are multiple ioctl number ranges that need to be handled */
#define MFI_LINUX_IOCTL_MIN 0x4d00
#define MFI_LINUX_IOCTL_MAX 0x4d04
static linux_ioctl_function_t mfi_linux_ioctl;
static struct linux_ioctl_handler mfi_linux_handler = {mfi_linux_ioctl,
MFI_LINUX_IOCTL_MIN,
MFI_LINUX_IOCTL_MAX};
SYSINIT (mfi_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_ioctl_register_handler, &mfi_linux_handler);
SYSUNINIT(mfi_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_ioctl_unregister_handler, &mfi_linux_handler);
static struct linux_device_handler mfi_device_handler =
{ "mfi", "megaraid_sas", "mfi0", "megaraid_sas_ioctl_node", -1, 0, 1};
SYSINIT (mfi_register2, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_device_register_handler, &mfi_device_handler);
SYSUNINIT(mfi_unregister2, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_device_unregister_handler, &mfi_device_handler);
static int
mfi_linux_modevent(module_t mod, int cmd, void *data)
{
return (0);
}
DEV_MODULE(mfi_linux, mfi_linux_modevent, NULL);
MODULE_DEPEND(mfi, linux, 1, 1, 1);
static int
mfi_linux_ioctl(d_thread_t *p, struct linux_ioctl_args *args)
{
struct file *fp;
int error;
if ((error = fget(p, args->fd, &fp)) != 0)
return (error);
error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p);
fdrop(fp, p);
return (error);
}

1586
sys/dev/sk/if_skreg.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../compat/linsysfs
KMOD= linsysfs
SRCS= vnode_if.h \
device_if.h bus_if.h pci_if.h \
linsysfs.c \
opt_compat.h
.include <bsd.kmod.mk>

View File

@ -0,0 +1,8 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../dev/mfi
KMOD= mfi_linux
SRCS= mfi_linux.c
.include <bsd.kmod.mk>

523
sys/pci/amdsmb.c Normal file
View File

@ -0,0 +1,523 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
#define AMDSMB_DEBUG(x) if (amdsmb_debug) (x)
#ifdef DEBUG
static int amdsmb_debug = 1;
#else
static int amdsmb_debug = 0;
#endif
#define AMDSMB_VENDORID_AMD 0x1022
#define AMDSMB_DEVICEID_AMD8111_SMB2 0x746a
/*
* ACPI 3.0, Chapter 12, Embedded Controller Interface.
*/
#define EC_DATA 0x00 /* data register */
#define EC_SC 0x04 /* status of controller */
#define EC_CMD 0x04 /* command register */
#define EC_SC_IBF 0x02 /* data ready for embedded controller */
#define EC_SC_OBF 0x01 /* data ready for host */
#define EC_CMD_WR 0x81 /* write EC */
#define EC_CMD_RD 0x80 /* read EC */
/*
* ACPI 3.0, Chapter 12, SMBus Host Controller Interface.
*/
#define SMB_PRTCL 0x00 /* protocol */
#define SMB_STS 0x01 /* status */
#define SMB_ADDR 0x02 /* address */
#define SMB_CMD 0x03 /* command */
#define SMB_DATA 0x04 /* 32 data registers */
#define SMB_BCNT 0x24 /* number of data bytes */
#define SMB_ALRM_A 0x25 /* alarm address */
#define SMB_ALRM_D 0x26 /* 2 bytes alarm data */
#define SMB_STS_DONE 0x80
#define SMB_STS_ALRM 0x40
#define SMB_STS_RES 0x20
#define SMB_STS_STATUS 0x1f
#define SMB_STS_OK 0x00 /* OK */
#define SMB_STS_UF 0x07 /* Unknown Failure */
#define SMB_STS_DANA 0x10 /* Device Address Not Acknowledged */
#define SMB_STS_DED 0x11 /* Device Error Detected */
#define SMB_STS_DCAD 0x12 /* Device Command Access Denied */
#define SMB_STS_UE 0x13 /* Unknown Error */
#define SMB_STS_DAD 0x17 /* Device Access Denied */
#define SMB_STS_T 0x18 /* Timeout */
#define SMB_STS_HUP 0x19 /* Host Unsupported Protocol */
#define SMB_STS_B 0x1a /* Busy */
#define SMB_STS_PEC 0x1f /* PEC (CRC-8) Error */
#define SMB_PRTCL_WRITE 0x00
#define SMB_PRTCL_READ 0x01
#define SMB_PRTCL_QUICK 0x02
#define SMB_PRTCL_BYTE 0x04
#define SMB_PRTCL_BYTE_DATA 0x06
#define SMB_PRTCL_WORD_DATA 0x08
#define SMB_PRTCL_BLOCK_DATA 0x0a
#define SMB_PRTCL_PROC_CALL 0x0c
#define SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define SMB_PRTCL_PEC 0x80
struct amdsmb_softc {
int rid;
struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
};
#define AMDSMB_ECINB(amdsmb, register) \
(bus_space_read_1(amdsmb->smbst, amdsmb->smbsh, register))
#define AMDSMB_ECOUTB(amdsmb, register, value) \
(bus_space_write_1(amdsmb->smbst, amdsmb->smbsh, register, value))
static int
amdsmb_probe(device_t dev)
{
u_int16_t vid;
u_int16_t did;
vid = pci_get_vendor(dev);
did = pci_get_device(dev);
if (vid == AMDSMB_VENDORID_AMD) {
switch(did) {
case AMDSMB_DEVICEID_AMD8111_SMB2:
device_set_desc(dev, "AMD-8111 SMBus 2.0 Controller");
return (BUS_PROBE_DEFAULT);
}
}
return (ENXIO);
}
static int
amdsmb_attach(device_t dev)
{
struct amdsmb_softc *amdsmb_sc = device_get_softc(dev);
/* Allocate I/O space */
amdsmb_sc->rid = PCIR_BAR(0);
amdsmb_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&amdsmb_sc->rid, RF_ACTIVE);
if (amdsmb_sc->res == NULL) {
device_printf(dev, "could not map i/o space\n");
return (ENXIO);
}
amdsmb_sc->smbst = rman_get_bustag(amdsmb_sc->res);
amdsmb_sc->smbsh = rman_get_bushandle(amdsmb_sc->res);
/* Allocate a new smbus device */
amdsmb_sc->smbus = device_add_child(dev, "smbus", -1);
if (!amdsmb_sc->smbus)
return (EINVAL);
bus_generic_attach(dev);
return (0);
}
static int
amdsmb_detach(device_t dev)
{
struct amdsmb_softc *amdsmb_sc = device_get_softc(dev);
if (amdsmb_sc->smbus) {
device_delete_child(dev, amdsmb_sc->smbus);
amdsmb_sc->smbus = NULL;
}
if (amdsmb_sc->res)
bus_release_resource(dev, SYS_RES_IOPORT, amdsmb_sc->rid,
amdsmb_sc->res);
return (0);
}
static int
amdsmb_callback(device_t dev, int index, caddr_t *data)
{
int error = 0;
switch (index) {
case SMB_REQUEST_BUS:
case SMB_RELEASE_BUS:
break;
default:
error = EINVAL;
}
return (error);
}
static int
amdsmb_ec_wait_write(struct amdsmb_softc *sc)
{
int timeout = 500;
while (timeout-- && AMDSMB_ECINB(sc, EC_SC) & EC_SC_IBF)
DELAY(1);
if (timeout == 0) {
device_printf(sc->smbus, "timeout waiting for IBF to clear\n");
return (1);
}
return (0);
}
static int
amdsmb_ec_wait_read(struct amdsmb_softc *sc)
{
int timeout = 500;
while (timeout-- && ~AMDSMB_ECINB(sc, EC_SC) & EC_SC_OBF)
DELAY(1);
if (timeout == 0) {
device_printf(sc->smbus, "timeout waiting for OBF to set\n");
return (1);
}
return (0);
}
static int
amdsmb_ec_read(struct amdsmb_softc *sc, u_char addr, u_char *data)
{
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_RD);
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_DATA, addr);
if (amdsmb_ec_wait_read(sc))
return (1);
*data = AMDSMB_ECINB(sc, EC_DATA);
return (0);
}
static int
amdsmb_ec_write(struct amdsmb_softc *sc, u_char addr, u_char data)
{
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_WR);
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_DATA, addr);
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_DATA, data);
return (0);
}
static int
amdsmb_wait(struct amdsmb_softc *sc)
{
u_char sts, temp;
int error, count;
amdsmb_ec_read(sc, SMB_PRTCL, &temp);
if (temp != 0)
{
count = 10000;
do {
DELAY(500);
amdsmb_ec_read(sc, SMB_PRTCL, &temp);
} while (temp != 0 && count--);
if (count == 0)
return (SMB_ETIMEOUT);
}
amdsmb_ec_read(sc, SMB_STS, &sts);
sts &= SMB_STS_STATUS;
AMDSMB_DEBUG(printf("amdsmb: STS=0x%x\n", sts));
switch (sts) {
case SMB_STS_OK:
error = SMB_ENOERR;
break;
case SMB_STS_DANA:
error = SMB_ENOACK;
break;
case SMB_STS_B:
error = SMB_EBUSY;
break;
case SMB_STS_T:
error = SMB_ETIMEOUT;
break;
case SMB_STS_DCAD:
case SMB_STS_DAD:
case SMB_STS_HUP:
error = SMB_ENOTSUPP;
break;
default:
error = SMB_EBUSERR;
break;
}
return (error);
}
static int
amdsmb_quick(device_t dev, u_char slave, int how)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
u_char protocol;
int error;
protocol = SMB_PRTCL_QUICK;
switch (how) {
case SMB_QWRITE:
protocol |= SMB_PRTCL_WRITE;
AMDSMB_DEBUG(printf("amdsmb: QWRITE to 0x%x", slave));
break;
case SMB_QREAD:
protocol |= SMB_PRTCL_READ;
AMDSMB_DEBUG(printf("amdsmb: QREAD to 0x%x", slave));
break;
default:
panic("%s: unknown QUICK command (%x)!", __func__, how);
}
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, protocol);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf(", error=0x%x\n", error));
return (error);
}
static int
amdsmb_sendb(device_t dev, u_char slave, char byte)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
amdsmb_ec_write(sc, SMB_CMD, byte);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf("amdsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n",
slave, byte, error));
return (error);
}
static int
amdsmb_recvb(device_t dev, u_char slave, char *byte)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE);
if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
amdsmb_ec_read(sc, SMB_DATA, byte);
AMDSMB_DEBUG(printf("amdsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n",
slave, *byte, error));
return (error);
}
static int
amdsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_DATA, byte);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE_DATA);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf("amdsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, "
"error=0x%x\n", slave, cmd, byte, error));
return (error);
}
static int
amdsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA);
if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
amdsmb_ec_read(sc, SMB_DATA, byte);
AMDSMB_DEBUG(printf("amdsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, "
"error=0x%x\n", slave, cmd, (unsigned char)*byte, error));
return (error);
}
static int
amdsmb_writew(device_t dev, u_char slave, char cmd, short word)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_DATA, word);
amdsmb_ec_write(sc, SMB_DATA + 1, word >> 8);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_WORD_DATA);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf("amdsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, "
"error=0x%x\n", slave, cmd, word, error));
return (error);
}
static int
amdsmb_readw(device_t dev, u_char slave, char cmd, short *word)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
u_char temp[2];
int error;
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA);
if ((error = amdsmb_wait(sc)) == SMB_ENOERR) {
amdsmb_ec_read(sc, SMB_DATA + 0, &temp[0]);
amdsmb_ec_read(sc, SMB_DATA + 1, &temp[1]);
*word = temp[0] | (temp[1] << 8);
}
AMDSMB_DEBUG(printf("amdsmb: READW from 0x%x, cmd=0x%x, word=0x%x, "
"error=0x%x\n", slave, cmd, (unsigned short)*word, error));
return (error);
}
static int
amdsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
u_char len, i;
int error;
len = min(count, 32);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_BCNT, len);
for (i = 0; i < len; i++)
amdsmb_ec_write(sc, SMB_DATA + i, buf[i]);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BLOCK_DATA);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf("amdsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, "
"error=0x%x", slave, count, cmd, error));
return (error);
}
static int
amdsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
u_char len, i;
int error;
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA);
if ((error = amdsmb_wait(sc)) == SMB_ENOERR) {
amdsmb_ec_read(sc, SMB_BCNT, &len);
len = min(len, 32);
for (i = 0; i < len; i++)
amdsmb_ec_read(sc, SMB_DATA + i, buf + i);
}
AMDSMB_DEBUG(printf("amdsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, "
"error=0x%x", slave, count, cmd, error));
return (error);
}
static device_method_t amdsmb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, amdsmb_probe),
DEVMETHOD(device_attach, amdsmb_attach),
DEVMETHOD(device_detach, amdsmb_detach),
/* SMBus interface */
DEVMETHOD(smbus_callback, amdsmb_callback),
DEVMETHOD(smbus_quick, amdsmb_quick),
DEVMETHOD(smbus_sendb, amdsmb_sendb),
DEVMETHOD(smbus_recvb, amdsmb_recvb),
DEVMETHOD(smbus_writeb, amdsmb_writeb),
DEVMETHOD(smbus_readb, amdsmb_readb),
DEVMETHOD(smbus_writew, amdsmb_writew),
DEVMETHOD(smbus_readw, amdsmb_readw),
DEVMETHOD(smbus_bwrite, amdsmb_bwrite),
DEVMETHOD(smbus_bread, amdsmb_bread),
{ 0, 0 }
};
static devclass_t amdsmb_devclass;
static driver_t amdsmb_driver = {
"amdsmb",
amdsmb_methods,
sizeof(struct amdsmb_softc),
};
DRIVER_MODULE(amdsmb, pci, amdsmb_driver, amdsmb_devclass, 0, 0);
MODULE_DEPEND(amdsmb, pci, 1, 1, 1);
MODULE_DEPEND(amdsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
MODULE_VERSION(amdsmb, 1);

552
sys/pci/nfsmb.c Normal file
View File

@ -0,0 +1,552 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
#define NFSMB_DEBUG(x) if (nfsmb_debug) (x)
#ifdef DEBUG
static int nfsmb_debug = 1;
#else
static int nfsmb_debug = 0;
#endif
/* NVIDIA nForce2/3/4 MCP */
#define NFSMB_VENDORID_NVIDIA 0x10de
#define NFSMB_DEVICEID_NF2_SMB 0x0064
#define NFSMB_DEVICEID_NF2_ULTRA_SMB 0x0084
#define NFSMB_DEVICEID_NF3_PRO150_SMB 0x00d4
#define NFSMB_DEVICEID_NF3_250GB_SMB 0x00e4
#define NFSMB_DEVICEID_NF4_SMB 0x0052
/* PCI Configuration space registers */
#define NF2PCI_SMBASE_1 PCIR_BAR(4)
#define NF2PCI_SMBASE_2 PCIR_BAR(5)
/*
* ACPI 3.0, Chapter 12, SMBus Host Controller Interface.
*/
#define SMB_PRTCL 0x00 /* protocol */
#define SMB_STS 0x01 /* status */
#define SMB_ADDR 0x02 /* address */
#define SMB_CMD 0x03 /* command */
#define SMB_DATA 0x04 /* 32 data registers */
#define SMB_BCNT 0x24 /* number of data bytes */
#define SMB_ALRM_A 0x25 /* alarm address */
#define SMB_ALRM_D 0x26 /* 2 bytes alarm data */
#define SMB_STS_DONE 0x80
#define SMB_STS_ALRM 0x40
#define SMB_STS_RES 0x20
#define SMB_STS_STATUS 0x1f
#define SMB_STS_OK 0x00 /* OK */
#define SMB_STS_UF 0x07 /* Unknown Failure */
#define SMB_STS_DANA 0x10 /* Device Address Not Acknowledged */
#define SMB_STS_DED 0x11 /* Device Error Detected */
#define SMB_STS_DCAD 0x12 /* Device Command Access Denied */
#define SMB_STS_UE 0x13 /* Unknown Error */
#define SMB_STS_DAD 0x17 /* Device Access Denied */
#define SMB_STS_T 0x18 /* Timeout */
#define SMB_STS_HUP 0x19 /* Host Unsupported Protocol */
#define SMB_STS_B 0x1A /* Busy */
#define SMB_STS_PEC 0x1F /* PEC (CRC-8) Error */
#define SMB_PRTCL_WRITE 0x00
#define SMB_PRTCL_READ 0x01
#define SMB_PRTCL_QUICK 0x02
#define SMB_PRTCL_BYTE 0x04
#define SMB_PRTCL_BYTE_DATA 0x06
#define SMB_PRTCL_WORD_DATA 0x08
#define SMB_PRTCL_BLOCK_DATA 0x0a
#define SMB_PRTCL_PROC_CALL 0x0c
#define SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define SMB_PRTCL_PEC 0x80
struct nfsmb_softc {
int rid;
struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
device_t subdev;
};
#define NFSMB_SMBINB(nfsmb, register) \
(bus_space_read_1(nfsmb->smbst, nfsmb->smbsh, register))
#define NFSMB_SMBOUTB(nfsmb, register, value) \
(bus_space_write_1(nfsmb->smbst, nfsmb->smbsh, register, value))
static int
nfsmbsub_probe(device_t dev)
{
device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller");
return (BUS_PROBE_DEFAULT);
}
static int
nfsmb_probe(device_t dev)
{
u_int16_t vid;
u_int16_t did;
vid = pci_get_vendor(dev);
did = pci_get_device(dev);
if (vid == NFSMB_VENDORID_NVIDIA) {
switch(did) {
case NFSMB_DEVICEID_NF2_SMB:
case NFSMB_DEVICEID_NF2_ULTRA_SMB:
case NFSMB_DEVICEID_NF3_PRO150_SMB:
case NFSMB_DEVICEID_NF3_250GB_SMB:
case NFSMB_DEVICEID_NF4_SMB:
device_set_desc(dev, "nForce2/3/4 MCP SMBus Controller");
return (BUS_PROBE_DEFAULT);
}
}
return (ENXIO);
}
static int
nfsmbsub_attach(device_t dev)
{
device_t parent;
struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev);
parent = device_get_parent(dev);
nfsmbsub_sc->rid = NF2PCI_SMBASE_2;
nfsmbsub_sc->res = bus_alloc_resource_any(parent, SYS_RES_IOPORT,
&nfsmbsub_sc->rid, RF_ACTIVE);
if (nfsmbsub_sc->res == NULL) {
device_printf(dev, "could not map i/o space\n");
return (ENXIO);
}
nfsmbsub_sc->smbst = rman_get_bustag(nfsmbsub_sc->res);
nfsmbsub_sc->smbsh = rman_get_bushandle(nfsmbsub_sc->res);
nfsmbsub_sc->smbus = device_add_child(dev, "smbus", -1);
if (nfsmbsub_sc->smbus == NULL)
return (EINVAL);
bus_generic_attach(dev);
return (0);
}
static int
nfsmb_attach(device_t dev)
{
struct nfsmb_softc *nfsmb_sc = device_get_softc(dev);
/* Allocate I/O space */
nfsmb_sc->rid = NF2PCI_SMBASE_1;
nfsmb_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&nfsmb_sc->rid, RF_ACTIVE);
if (nfsmb_sc->res == NULL) {
device_printf(dev, "could not map i/o space\n");
return (ENXIO);
}
nfsmb_sc->smbst = rman_get_bustag(nfsmb_sc->res);
nfsmb_sc->smbsh = rman_get_bushandle(nfsmb_sc->res);
/* Allocate a new smbus device */
nfsmb_sc->smbus = device_add_child(dev, "smbus", -1);
if (!nfsmb_sc->smbus)
return (EINVAL);
nfsmb_sc->subdev = NULL;
switch (pci_get_device(dev)) {
case NFSMB_DEVICEID_NF2_SMB:
case NFSMB_DEVICEID_NF2_ULTRA_SMB:
case NFSMB_DEVICEID_NF3_PRO150_SMB:
case NFSMB_DEVICEID_NF3_250GB_SMB:
case NFSMB_DEVICEID_NF4_SMB:
/* Trying to add secondary device as slave */
nfsmb_sc->subdev = device_add_child(dev, "nfsmb", -1);
if (!nfsmb_sc->subdev)
return (EINVAL);
break;
default:
break;
}
bus_generic_attach(dev);
return (0);
}
static int
nfsmbsub_detach(device_t dev)
{
device_t parent;
struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev);
parent = device_get_parent(dev);
if (nfsmbsub_sc->smbus) {
device_delete_child(dev, nfsmbsub_sc->smbus);
nfsmbsub_sc->smbus = NULL;
}
if (nfsmbsub_sc->res) {
bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid,
nfsmbsub_sc->res);
nfsmbsub_sc->res = NULL;
}
return (0);
}
static int
nfsmb_detach(device_t dev)
{
struct nfsmb_softc *nfsmb_sc = device_get_softc(dev);
if (nfsmb_sc->subdev) {
device_delete_child(dev, nfsmb_sc->subdev);
nfsmb_sc->subdev = NULL;
}
if (nfsmb_sc->smbus) {
device_delete_child(dev, nfsmb_sc->smbus);
nfsmb_sc->smbus = NULL;
}
if (nfsmb_sc->res) {
bus_release_resource(dev, SYS_RES_IOPORT, nfsmb_sc->rid,
nfsmb_sc->res);
nfsmb_sc->res = NULL;
}
return (0);
}
static int
nfsmb_callback(device_t dev, int index, caddr_t *data)
{
int error = 0;
switch (index) {
case SMB_REQUEST_BUS:
case SMB_RELEASE_BUS:
break;
default:
error = EINVAL;
}
return (error);
}
static int
nfsmb_wait(struct nfsmb_softc *sc)
{
u_char sts;
int error, count;
if (NFSMB_SMBINB(sc, SMB_PRTCL) != 0)
{
count = 10000;
do {
DELAY(500);
} while (NFSMB_SMBINB(sc, SMB_PRTCL) != 0 && count--);
if (count == 0)
return (SMB_ETIMEOUT);
}
sts = NFSMB_SMBINB(sc, SMB_STS) & SMB_STS_STATUS;
NFSMB_DEBUG(printf("nfsmb: STS=0x%x\n", sts));
switch (sts) {
case SMB_STS_OK:
error = SMB_ENOERR;
break;
case SMB_STS_DANA:
error = SMB_ENOACK;
break;
case SMB_STS_B:
error = SMB_EBUSY;
break;
case SMB_STS_T:
error = SMB_ETIMEOUT;
break;
case SMB_STS_DCAD:
case SMB_STS_DAD:
case SMB_STS_HUP:
error = SMB_ENOTSUPP;
break;
default:
error = SMB_EBUSERR;
break;
}
return (error);
}
static int
nfsmb_quick(device_t dev, u_char slave, int how)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
u_char protocol;
int error;
protocol = SMB_PRTCL_QUICK;
switch (how) {
case SMB_QWRITE:
protocol |= SMB_PRTCL_WRITE;
NFSMB_DEBUG(printf("nfsmb: QWRITE to 0x%x", slave));
break;
case SMB_QREAD:
protocol |= SMB_PRTCL_READ;
NFSMB_DEBUG(printf("nfsmb: QREAD to 0x%x", slave));
break;
default:
panic("%s: unknown QUICK command (%x)!", __func__, how);
}
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, protocol);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf(", error=0x%x\n", error));
return (error);
}
static int
nfsmb_sendb(device_t dev, u_char slave, char byte)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, byte);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
return (error);
}
static int
nfsmb_recvb(device_t dev, u_char slave, char *byte)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE);
if ((error = nfsmb_wait(sc)) == SMB_ENOERR)
*byte = NFSMB_SMBINB(sc, SMB_DATA);
NFSMB_DEBUG(printf("nfsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
return (error);
}
static int
nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_DATA, byte);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE_DATA);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
return (error);
}
static int
nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA);
if ((error = nfsmb_wait(sc)) == SMB_ENOERR)
*byte = NFSMB_SMBINB(sc, SMB_DATA);
NFSMB_DEBUG(printf("nfsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, (unsigned char)*byte, error));
return (error);
}
static int
nfsmb_writew(device_t dev, u_char slave, char cmd, short word)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_DATA, word);
NFSMB_SMBOUTB(sc, SMB_DATA + 1, word >> 8);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_WORD_DATA);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
return (error);
}
static int
nfsmb_readw(device_t dev, u_char slave, char cmd, short *word)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA);
if ((error = nfsmb_wait(sc)) == SMB_ENOERR)
*word = NFSMB_SMBINB(sc, SMB_DATA) |
(NFSMB_SMBINB(sc, SMB_DATA + 1) << 8);
NFSMB_DEBUG(printf("nfsmb: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, (unsigned short)*word, error));
return (error);
}
static int
nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
u_char len, i;
int error;
len = min(count, 32);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_BCNT, len);
for (i = 0; i < len; i++)
NFSMB_SMBOUTB(sc, SMB_DATA + i, buf[i]);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BLOCK_DATA);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
return (error);
}
static int
nfsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
u_char len, i;
int error;
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA);
if ((error = nfsmb_wait(sc)) == SMB_ENOERR) {
len = NFSMB_SMBINB(sc, SMB_BCNT);
len = min(len, 32);
for (i = 0; i < len; i++)
buf[i] = NFSMB_SMBINB(sc, SMB_DATA + i);
}
NFSMB_DEBUG(printf("nfsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
return (error);
}
static device_method_t nfsmb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nfsmb_probe),
DEVMETHOD(device_attach, nfsmb_attach),
DEVMETHOD(device_detach, nfsmb_detach),
/* SMBus interface */
DEVMETHOD(smbus_callback, nfsmb_callback),
DEVMETHOD(smbus_quick, nfsmb_quick),
DEVMETHOD(smbus_sendb, nfsmb_sendb),
DEVMETHOD(smbus_recvb, nfsmb_recvb),
DEVMETHOD(smbus_writeb, nfsmb_writeb),
DEVMETHOD(smbus_readb, nfsmb_readb),
DEVMETHOD(smbus_writew, nfsmb_writew),
DEVMETHOD(smbus_readw, nfsmb_readw),
DEVMETHOD(smbus_bwrite, nfsmb_bwrite),
DEVMETHOD(smbus_bread, nfsmb_bread),
{ 0, 0 }
};
static device_method_t nfsmbsub_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nfsmbsub_probe),
DEVMETHOD(device_attach, nfsmbsub_attach),
DEVMETHOD(device_detach, nfsmbsub_detach),
/* SMBus interface */
DEVMETHOD(smbus_callback, nfsmb_callback),
DEVMETHOD(smbus_quick, nfsmb_quick),
DEVMETHOD(smbus_sendb, nfsmb_sendb),
DEVMETHOD(smbus_recvb, nfsmb_recvb),
DEVMETHOD(smbus_writeb, nfsmb_writeb),
DEVMETHOD(smbus_readb, nfsmb_readb),
DEVMETHOD(smbus_writew, nfsmb_writew),
DEVMETHOD(smbus_readw, nfsmb_readw),
DEVMETHOD(smbus_bwrite, nfsmb_bwrite),
DEVMETHOD(smbus_bread, nfsmb_bread),
{ 0, 0 }
};
static devclass_t nfsmb_devclass;
static driver_t nfsmb_driver = {
"nfsmb",
nfsmb_methods,
sizeof(struct nfsmb_softc),
};
static driver_t nfsmbsub_driver = {
"nfsmb",
nfsmbsub_methods,
sizeof(struct nfsmb_softc),
};
DRIVER_MODULE(nfsmb, pci, nfsmb_driver, nfsmb_devclass, 0, 0);
DRIVER_MODULE(nfsmb, nfsmb, nfsmbsub_driver, nfsmb_devclass, 0, 0);
MODULE_DEPEND(nfsmb, pci, 1, 1, 1);
MODULE_DEPEND(nfsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
MODULE_VERSION(nfsmb, 1);

View File

@ -0,0 +1,65 @@
#!/bin/sh
# $FreeBSD$
base=`basename $0`
no=45
sectors=100
keyfile=`mktemp /tmp/$base.XXXXXX` || exit 1
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
echo "1..8"
geli init -P md${no} 2>/dev/null
if [ $? -ne 0 ]; then
echo "ok 1"
else
echo "not ok 1"
fi
dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1
geli init -P -K ${keyfile} md${no} 2>/dev/null
if [ $? -eq 0 ]; then
echo "ok 2"
else
echo "not ok 2"
fi
geli attach -p md${no} 2>/dev/null
if [ $? -ne 0 ]; then
echo "ok 3"
else
echo "not ok 3"
fi
geli attach -p -k ${keyfile} md${no} 2>/dev/null
if [ $? -eq 0 ]; then
echo "ok 4"
else
echo "not ok 4"
fi
geli setkey -n 0 -P md${no} 2>/dev/null
if [ $? -ne 0 ]; then
echo "ok 5"
else
echo "not ok 5"
fi
geli detach md${no} 2>/dev/null
if [ $? -eq 0 ]; then
echo "ok 6"
else
echo "not ok 6"
fi
geli setkey -n 0 -p -P -K ${keyfile} md${no} 2>/dev/null
if [ $? -ne 0 ]; then
echo "ok 7"
else
echo "not ok 7"
fi
geli setkey -n 0 -p -k ${keyfile} -P md${no} 2>/dev/null
if [ $? -ne 0 ]; then
echo "ok 8"
else
echo "not ok 8"
fi
mdconfig -d -u $no
rm -f $keyfile

View File

@ -0,0 +1,128 @@
.\" Copyright (c) 2006 Ulrich Spoerlein <uspoerlein@gmail.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd May 6, 2006
.Dt RECOVERDISK 1
.Os
.Sh NAME
.Nm recoverdisk
.Nd recover data from hard disk or optical media
.Sh SYNOPSIS
.Nm
.Op Fl r Ar rlist
.Op Fl w Ar wlist
.Ar special
.Op file
.Sh DESCRIPTION
The
.Nm
utility reads data from the
.Pa special
file until all blocks could be successfully read.
It starts reading in multiples of the sector size.
Whenever a block fails, it is put to the end of the working queue and will be
read again, possibly with a smaller read size.
.Pp
It uses block sizes of roughly 1 MB, 64kB, and the native sector size (usually
512 bytes).
These figures are adjusted slightly, for devices whose sectorsize is not a
power of 2, e.g., audio CDs with a sector size of 2352 bytes.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl r Ar rlist
Read the list of blocks and block sizes to read from the specified file.
.It Fl w Ar wlist
Write the list of remaining blocks to read to the specified file if
.Nm
is aborted via SIGINT.
.El
.Pp
The
.Fl r
and
.Fl w
option can be used in combination.
Especially, they can point to the same file, which will be updated on abort.
.Sh OUTPUT
.Nm
prints several columns, detailing the progress
.Bl -tag -width remaining
.It start
Starting offset of the current block.
.It size
Read size of the current block.
.It len
Length of the current block.
.It state
Is increased for every failed read.
.It done
Number of bytes already read.
.It remaining
Number of bytes remaining.
.It % done
Percent complete.
.El
.Sh EXAMPLES
# recover data from failing hard drive ad3
.Dl $ touch /data/lots_of_space
.Dl $ recoverdisk /dev/ad3 /data/lots_of_space
.Pp
# clone a hard disk
.Dl $ recoverdisk /dev/ad3 /dev/ad4
.Pp
# read an ISO image from a CD-ROM
.Dl $ touch /data/cd.iso; recoverdisk /dev/acd0 /data/cd.iso
.Pp
# continue reading from a broken CD and update the existing worklist
.Dl $ recoverdisk -r worklist -w worklist /dev/acd0 /data/cd.iso
.Pp
# recover a single file from the unreadable media
.Dl $ touch file.avi; recoverdisk /cdrom/file.avi file.avi
.Sh SEE ALSO
.Xr dd 1
.Sh HISTORY
The
.Nm
command first appeared in
.Fx 7.0 .
.Sh BUGS
Reading from media where the sectorsize is not a power of 2 will make all
1 MB reads fail.
This is due to the DMA reads being split up into blocks of at most 128kB.
These reads then fail if the sectorsize is not a divisor of 128kB.
When reading a full raw audio CD, this leads to roughly 700 error messages
flying by.
This is harmless.
.Sh AUTHORS
.An -nosplit
The original implementation was done by
.An Poul-Henning Kamp Aq phk@freebsd.org
with minor improvements from
.An Ulrich Sp\(:orlein Aq uspoerlein@gmail.com .
.Pp
This manual page was written by
.An Ulrich Sp\(:orlein Aq uspoerlein@gmail.com .

6
usr.bin/getent/Makefile Normal file
View File

@ -0,0 +1,6 @@
# $FreeBSD$
PROG= getent
WARNS?= 3
.include <bsd.prog.mk>

129
usr.bin/getent/getent.1 Normal file
View File

@ -0,0 +1,129 @@
.\" $NetBSD: getent.1,v 1.13 2005/09/11 23:16:15 wiz Exp $
.\"
.\" Copyright (c) 2004 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Luke Mewburn.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd August 24, 2005
.Dt GETENT 1
.Os
.Sh NAME
.Nm getent
.Nd get entries from administrative database
.Sh SYNOPSIS
.Nm
.Ar database
.Op Ar key ...
.Sh DESCRIPTION
The
.Nm
program retrieves and displays entries from the administrative
database specified by
.Ar database ,
using the lookup order specified in
.Xr nsswitch.conf 5 .
The display format for a given
.Ar database
is as per the
.Dq traditional
file format for that database.
.Pp
.Ar database
may be one of:
.Bl -column "netgroup" -offset indent -compact
.Sy Database Ta Sy Display format
.It ethers Ta address name
.It group Ta group:passwd:gid:[member[,member]...]
.It hosts Ta address name [alias ...]
.It networks Ta name network [alias ...]
.It passwd Ta user:passwd:uid:gid:gecos:home_dir:shell
.It protocols Ta name protocol [alias ...]
.It rpc Ta name number [alias ...]
.It services Ta name port/protocol [alias ...]
.It shells Ta /path/to/shell
.El
.Pp
If one or more
.Ar key
arguments are provided, they will be looked up in
.Ar database
using the appropriate function.
For example,
.Sy passwd
supports a numeric UID or user name;
.Sy hosts
supports an IPv4 address, IPv6 address, or host name;
and
.Sy services
supports a service name, service name/protocol name, numeric port, or
numeric port/protocol name.
.Pp
If no
.Ar key
is provided and
.Ar database
supports enumeration, all entries for
.Ar database
will be retrieved using the appropriate enumeration function and printed.
.Sh DIAGNOSTICS
.Nm
exits 0 on success,
1 if there was an error in the command syntax,
2 if one of the specified key names was not found in
.Ar database ,
or 3 if there is no support for enumeration on
.Ar database .
.Sh SEE ALSO
.Xr ethers 5 ,
.Xr group 5 ,
.Xr hosts 5 ,
.Xr networks 5 ,
.Xr nsswitch.conf 5 ,
.Xr passwd 5 ,
.Xr protocols 5 ,
.Xr rpc 5 ,
.Xr services 5 ,
.Xr shells 5
.Sh HISTORY
A
.Nm
command appeared in
.Nx 3.0 ,
and was imported into
.Fx 7.0 .
It was based on the command of the same name in
.Tn Solaris
and
.Tn Linux .

564
usr.bin/getent/getent.c Normal file
View File

@ -0,0 +1,564 @@
/* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/in.h> /* for INET6_ADDRSTRLEN */
#include <rpc/rpcent.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int usage(void);
static int parsenum(const char *, unsigned long *);
static int ethers(int, char *[]);
static int group(int, char *[]);
static int hosts(int, char *[]);
static int networks(int, char *[]);
static int passwd(int, char *[]);
static int protocols(int, char *[]);
static int rpc(int, char *[]);
static int services(int, char *[]);
static int shells(int, char *[]);
enum {
RV_OK = 0,
RV_USAGE = 1,
RV_NOTFOUND = 2,
RV_NOENUM = 3,
};
static struct getentdb {
const char *name;
int (*callback)(int, char *[]);
} databases[] = {
{ "ethers", ethers, },
{ "group", group, },
{ "hosts", hosts, },
{ "networks", networks, },
{ "passwd", passwd, },
{ "protocols", protocols, },
{ "rpc", rpc, },
{ "services", services, },
{ "shells", shells, },
{ NULL, NULL, },
};
int
main(int argc, char *argv[])
{
struct getentdb *curdb;
setprogname(argv[0]);
if (argc < 2)
usage();
for (curdb = databases; curdb->name != NULL; curdb++) {
if (strcmp(curdb->name, argv[1]) == 0) {
exit(curdb->callback(argc, argv));
break;
}
}
fprintf(stderr, "Unknown database: %s\n", argv[1]);
usage();
/* NOTREACHED */
return RV_USAGE;
}
static int
usage(void)
{
struct getentdb *curdb;
fprintf(stderr, "Usage: %s database [key ...]\n",
getprogname());
fprintf(stderr, " database may be one of:\n\t");
for (curdb = databases; curdb->name != NULL; curdb++) {
fprintf(stderr, " %s", curdb->name);
}
fprintf(stderr, "\n");
exit(RV_USAGE);
/* NOTREACHED */
}
static int
parsenum(const char *word, unsigned long *result)
{
unsigned long num;
char *ep;
assert(word != NULL);
assert(result != NULL);
if (!isdigit((unsigned char)word[0]))
return 0;
errno = 0;
num = strtoul(word, &ep, 10);
if (num == ULONG_MAX && errno == ERANGE)
return 0;
if (*ep != '\0')
return 0;
*result = num;
return 1;
}
/*
* printfmtstrings --
* vprintf(format, ...),
* then the aliases (beginning with prefix, separated by sep),
* then a newline
*/
static void
printfmtstrings(char *strings[], const char *prefix, const char *sep,
const char *fmt, ...)
{
va_list ap;
const char *curpref;
int i;
va_start(ap, fmt);
vprintf(fmt, ap);
curpref = prefix;
for (i = 0; strings[i] != NULL; i++) {
printf("%s%s", curpref, strings[i]);
curpref = sep;
}
printf("\n");
}
/*
* ethers
*/
static int
ethers(int argc, char *argv[])
{
char hostname[MAXHOSTNAMELEN + 1], *hp;
struct ether_addr ea, *eap;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp)
rv = RV_OK;
if (argc == 2) {
fprintf(stderr, "Enumeration not supported on ethers\n");
rv = RV_NOENUM;
} else {
for (i = 2; i < argc; i++) {
if ((eap = ether_aton(argv[i])) == NULL) {
eap = &ea;
hp = argv[i];
if (ether_hostton(hp, eap) != 0) {
rv = RV_NOTFOUND;
break;
}
} else {
hp = hostname;
if (ether_ntohost(hp, eap) != 0) {
rv = RV_NOTFOUND;
break;
}
}
ETHERSPRINT;
}
}
return rv;
}
/*
* group
*/
static int
group(int argc, char *argv[])
{
struct group *gr;
unsigned long id;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \
gr->gr_name, gr->gr_passwd, gr->gr_gid)
setgroupent(1);
rv = RV_OK;
if (argc == 2) {
while ((gr = getgrent()) != NULL)
GROUPPRINT;
} else {
for (i = 2; i < argc; i++) {
if (parsenum(argv[i], &id))
gr = getgrgid((gid_t)id);
else
gr = getgrnam(argv[i]);
if (gr != NULL)
GROUPPRINT;
else {
rv = RV_NOTFOUND;
break;
}
}
}
endgrent();
return rv;
}
/*
* hosts
*/
static void
hostsprint(const struct hostent *he)
{
char buf[INET6_ADDRSTRLEN];
assert(he != NULL);
if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
strlcpy(buf, "# unknown", sizeof(buf));
printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
}
static int
hosts(int argc, char *argv[])
{
struct hostent *he;
char addr[IN6ADDRSZ];
int i, rv;
assert(argc > 1);
assert(argv != NULL);
sethostent(1);
rv = RV_OK;
if (argc == 2) {
while ((he = gethostent()) != NULL)
hostsprint(he);
} else {
for (i = 2; i < argc; i++) {
if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
he = gethostbyaddr(addr, INADDRSZ, AF_INET);
else
he = gethostbyname(argv[i]);
if (he != NULL)
hostsprint(he);
else {
rv = RV_NOTFOUND;
break;
}
}
}
endhostent();
return rv;
}
/*
* networks
*/
static void
networksprint(const struct netent *ne)
{
char buf[INET6_ADDRSTRLEN];
struct in_addr ianet;
assert(ne != NULL);
ianet = inet_makeaddr(ne->n_net, 0);
if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
strlcpy(buf, "# unknown", sizeof(buf));
printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
}
static int
networks(int argc, char *argv[])
{
struct netent *ne;
in_addr_t net;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
setnetent(1);
rv = RV_OK;
if (argc == 2) {
while ((ne = getnetent()) != NULL)
networksprint(ne);
} else {
for (i = 2; i < argc; i++) {
net = inet_network(argv[i]);
if (net != INADDR_NONE)
ne = getnetbyaddr(net, AF_INET);
else
ne = getnetbyname(argv[i]);
if (ne != NULL)
networksprint(ne);
else {
rv = RV_NOTFOUND;
break;
}
}
}
endnetent();
return rv;
}
/*
* passwd
*/
static int
passwd(int argc, char *argv[])
{
struct passwd *pw;
unsigned long id;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \
pw->pw_name, pw->pw_passwd, pw->pw_uid, \
pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
setpassent(1);
rv = RV_OK;
if (argc == 2) {
while ((pw = getpwent()) != NULL)
PASSWDPRINT;
} else {
for (i = 2; i < argc; i++) {
if (parsenum(argv[i], &id))
pw = getpwuid((uid_t)id);
else
pw = getpwnam(argv[i]);
if (pw != NULL)
PASSWDPRINT;
else {
rv = RV_NOTFOUND;
break;
}
}
}
endpwent();
return rv;
}
/*
* protocols
*/
static int
protocols(int argc, char *argv[])
{
struct protoent *pe;
unsigned long id;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \
"%-16s %5d", pe->p_name, pe->p_proto)
setprotoent(1);
rv = RV_OK;
if (argc == 2) {
while ((pe = getprotoent()) != NULL)
PROTOCOLSPRINT;
} else {
for (i = 2; i < argc; i++) {
if (parsenum(argv[i], &id))
pe = getprotobynumber((int)id);
else
pe = getprotobyname(argv[i]);
if (pe != NULL)
PROTOCOLSPRINT;
else {
rv = RV_NOTFOUND;
break;
}
}
}
endprotoent();
return rv;
}
/*
* rpc
*/
static int
rpc(int argc, char *argv[])
{
struct rpcent *re;
unsigned long id;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \
"%-16s %6d", \
re->r_name, re->r_number)
setrpcent(1);
rv = RV_OK;
if (argc == 2) {
while ((re = getrpcent()) != NULL)
RPCPRINT;
} else {
for (i = 2; i < argc; i++) {
if (parsenum(argv[i], &id))
re = getrpcbynumber((int)id);
else
re = getrpcbyname(argv[i]);
if (re != NULL)
RPCPRINT;
else {
rv = RV_NOTFOUND;
break;
}
}
}
endrpcent();
return rv;
}
/*
* services
*/
static int
services(int argc, char *argv[])
{
struct servent *se;
unsigned long id;
char *proto;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \
"%-16s %5d/%s", \
se->s_name, ntohs(se->s_port), se->s_proto)
setservent(1);
rv = RV_OK;
if (argc == 2) {
while ((se = getservent()) != NULL)
SERVICESPRINT;
} else {
for (i = 2; i < argc; i++) {
proto = strchr(argv[i], '/');
if (proto != NULL)
*proto++ = '\0';
if (parsenum(argv[i], &id))
se = getservbyport(htons((u_short)id), proto);
else
se = getservbyname(argv[i], proto);
if (se != NULL)
SERVICESPRINT;
else {
rv = RV_NOTFOUND;
break;
}
}
}
endservent();
return rv;
}
/*
* shells
*/
static int
shells(int argc, char *argv[])
{
const char *sh;
int i, rv;
assert(argc > 1);
assert(argv != NULL);
#define SHELLSPRINT printf("%s\n", sh)
setusershell();
rv = RV_OK;
if (argc == 2) {
while ((sh = getusershell()) != NULL)
SHELLSPRINT;
} else {
for (i = 2; i < argc; i++) {
setusershell();
while ((sh = getusershell()) != NULL) {
if (strcmp(sh, argv[i]) == 0) {
SHELLSPRINT;
break;
}
}
if (sh == NULL) {
rv = RV_NOTFOUND;
break;
}
}
}
endusershell();
return rv;
}

View File

@ -0,0 +1,19 @@
#
# From: Id: Makefile,v 1.2 2004/01/15 16:20:56 pkern Exp
#
# $FreeBSD$
#
PROG= ipfwpcap
LDADD= -lpcap
DPADD= ${LIBPCAP}
MAN= ipfwpcap.8
.include <bsd.prog.mk>
test: $(CMD)
-rm /var/run/ipfwpcap.2000.pid
./ipfwpcap -d 2000 - | tcpdump -r - -n -s 2000 -X

View File

@ -0,0 +1,583 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 17, 2006
.Dt NTP-KEYGEN. 8
.Os
.Sh NAME
.Nm ntp-keygen
.Nd key generation program for ntpd
.Sh SYNOPSIS
.Nm
.Op Fl deGgHIMnPT
.Op Fl c Oo Cm RSA-MD2 | RSA-MD5 | RSA-SHA | RSA-SHA1 | RSA-MDC2 | RSA-RIPEMD160 | DSA-SHA | DSA-SHA1 Oc
.Op Fl i Ar name
.Op Fl p Ar password
.Op Fl S Oo Cm RSA | DSA Oc
.Op Fl s Ar name
.Op Fl v Ar nkeys
.Sh DESCRIPTION
This program generates cryptographic data files used by the NTPv4
authentication and identification schemes.
It generates MD5 key files used in symmetric key cryptography.
In addition, if the OpenSSL software library has been installed,
it generates keys, certificate and identity files used in public key
cryptography. These files are used for cookie encryption,
digital signature and challenge/response identification algorithms
compatible with the Internet standard security infrastructure.
.Pp
All files are in PEM-encoded printable ASCII format,
so they can be embedded as MIME attachments in mail to other sites
and certificate authorities.
By default, files are not encrypted. The
.Fl p Ar password
option specifies the write password and
.Fl q Ar password
option the read password for previously encrypted files.
The
.Nm
program prompts for the password if it reads an encrypted file
and the password is missing or incorrect.
If an encrypted file is read successfully and
no write password is specified, the read password is used
as the write password by default.
.Pp
The
.Xr ntpd 8
configuration command
.Ic crypto pw Ar password
specifies the read password for previously encrypted files.
The daemon expires on the spot if the password is missing
or incorrect.
For convenience, if a file has been previously encrypted,
the default read password is the name of the host running
the program.
If the previous write password is specified as the host name,
these files can be read by that host with no explicit password.
.Pp
File names begin with the prefix
.Cm ntpkey_
and end with the postfix
.Ar _hostname.filestamp ,
where
.Ar hostname
is the owner name, usually the string returned
by the Unix gethostname() routine, and
.Ar filestamp
is the NTP seconds when the file was generated, in decimal digits.
This both guarantees uniqueness and simplifies maintenance
procedures, since all files can be quickly removed
by a
.Ic rm ntpkey\&*
command or all files generated
at a specific time can be removed by a
.Ic rm
.Ar \&*filestamp
command.
To further reduce the risk of misconfiguration,
the first two lines of a file contain the file name
and generation date and time as comments.
.Pp
All files are installed by default in the keys directory
.Pa /usr/local/etc ,
which is normally in a shared filesystem
in NFS-mounted networks. The actual location of the keys directory
and each file can be overridden by configuration commands,
but this is not recommended.
Normally, the files for each host are generated by that host
and used only by that host, although exceptions exist
as noted later on this page.
.Pp
Normally, files containing private values,
including the host key, sign key and identification parameters,
are permitted root read/write-only;
while others containing public values are permitted world readable.
Alternatively, files containing private values can be encrypted
and these files permitted world readable,
which simplifies maintenance in shared file systems.
Since uniqueness is insured by the hostname and
file name extensions, the files for a NFS server and
dependent clients can all be installed in the same shared directory.
.Pp
The recommended practice is to keep the file name extensions
when installing a file and to install a soft link
from the generic names specified elsewhere on this page
to the generated files.
This allows new file generations to be activated simply
by changing the link.
If a link is present, ntpd follows it to the file name
to extract the filestamp.
If a link is not present,
.Xr ntpd 8
extracts the filestamp from the file itself.
This allows clients to verify that the file and generation times
are always current. The
.Nm
program uses the same timestamp extension for all files generated
at one time, so each generation is distinct and can be readily
recognized in monitoring data.
.Ss Running the program
The safest way to run the
.Nm
program is logged in directly as root.
The recommended procedure is change to the keys directory,
usually
.Pa /ust/local/etc ,
then run the program. When run for the first time,
or if all
.Cm ntpkey
files have been removed,
the program generates a RSA host key file and matching RSA-MD5 certificate file,
which is all that is necessary in many cases.
The program also generates soft links from the generic names
to the respective files.
If run again, the program uses the same host key file,
but generates a new certificate file and link.
.Pp
The host key is used to encrypt the cookie when required and so must be RSA type.
By default, the host key is also the sign key used to encrypt signatures.
When necessary, a different sign key can be specified and this can be
either RSA or DSA type.
By default, the message digest type is MD5, but any combination
of sign key type and message digest type supported by the OpenSSL library
can be specified, including those using the MD2, MD5, SHA, SHA1, MDC2
and RIPE160 message digest algorithms.
However, the scheme specified in the certificate must be compatible
with the sign key.
Certificates using any digest algorithm are compatible with RSA sign keys;
however, only SHA and SHA1 certificates are compatible with DSA sign keys.
.Pp
Private/public key files and certificates are compatible with
other OpenSSL applications and very likely other libraries as well.
Certificates or certificate requests derived from them should be compatible
with extant industry practice, although some users might find
the interpretation of X509v3 extension fields somewhat liberal.
However, the identification parameter files, although encoded
as the other files, are probably not compatible with anything other than Autokey.
.Pp
Running the program as other than root and using the Unix
.Ic su
command
to assume root may not work properly, since by default the OpenSSL library
looks for the random seed file
.Cm .rnd
in the user home directory.
However, there should be only one
.Cm .rnd ,
most conveniently
in the root directory, so it is convenient to define the
.Cm $RANDFILE
environment variable used by the OpenSSL library as the path to
.Cm /.rnd .
.Pp
Installing the keys as root might not work in NFS-mounted
shared file systems, as NFS clients may not be able to write
to the shared keys directory, even as root.
In this case, NFS clients can specify the files in another
directory such as
.Pa /etc
using the
.Ic keysdir
command.
There is no need for one client to read the keys and certificates
of other clients or servers, as these data are obtained automatically
by the Autokey protocol.
.Pp
Ordinarily, cryptographic files are generated by the host that uses them,
but it is possible for a trusted agent (TA) to generate these files
for other hosts; however, in such cases files should always be encrypted.
The subject name and trusted name default to the hostname
of the host generating the files, but can be changed by command line options.
It is convenient to designate the owner name and trusted name
as the subject and issuer fields, respectively, of the certificate.
The owner name is also used for the host and sign key files,
while the trusted name is used for the identity files.
.Pp
.Ss Trusted Hosts and Groups
Each cryptographic configuration involves selection of a signature scheme
and identification scheme, called a cryptotype,
as explained in the
.Sx Authentication Options
section of
.Xr ntp.conf 5 .
The default cryptotype uses RSA encryption, MD5 message digest
and TC identification.
First, configure a NTP subnet including one or more low-stratum
trusted hosts from which all other hosts derive synchronization
directly or indirectly. Trusted hosts have trusted certificates;
all other hosts have nontrusted certificates.
These hosts will automatically and dynamically build authoritative
certificate trails to one or more trusted hosts.
A trusted group is the set of all hosts that have, directly or indirectly,
a certificate trail ending at a trusted host.
The trail is defined by static configuration file entries
or dynamic means described on the
.Sx Automatic NTP Configuration Options
section of
.Xr ntp.conf 5 .
.Pp
On each trusted host as root, change to the keys directory.
To insure a fresh fileset, remove all
.Cm ntpkey
files.
Then run
.Nm
.Fl T
to generate keys and a trusted certificate.
On all other hosts do the same, but leave off the
.Fl T
flag to generate keys and nontrusted certificates.
When complete, start the NTP daemons beginning at the lowest stratum
and working up the tree.
It may take some time for Autokey to instantiate the certificate trails
throughout the subnet, but setting up the environment is completely automatic.
.Pp
If it is necessary to use a different sign key or different digest/signature
scheme than the default, run
.Nm
with the
.Fl S Ar type
option, where
.Ar type
is either
.Cm RSA
or
.Cm DSA .
The most often need to do this is when a DSA-signed certificate is used.
If it is necessary to use a different certificate scheme than the default,
run
.Nm
with the
.Fl c Ar scheme
option and selected
.Ar scheme
as needed.
If
.Nm
is run again without these options, it generates a new certificate
using the same scheme and sign key.
.Pp
After setting up the environment it is advisable to update certificates
from time to time, if only to extend the validity interval.
Simply run
.Nm
with the same flags as before to generate new certificates
using existing keys.
However, if the host or sign key is changed,
.Xr ntpd 8
should be restarted.
When
.Xr ntpd 8
is restarted, it loads any new files and restarts the protocol.
Other dependent hosts will continue as usual until signatures are refreshed,
at which time the protocol is restarted.
.Ss Identity Schemes
As mentioned on the Autonomous Authentication page,
the default TC identity scheme is vulnerable to a middleman attack.
However, there are more secure identity schemes available,
including PC, IFF, GQ and MV described on the
.Qq Identification Schemes
page
(maybe available at
.Li http://www.eecis.udel.edu/%7emills/keygen.html ) .
These schemes are based on a TA, one or more trusted hosts
and some number of nontrusted hosts.
Trusted hosts prove identity using values provided by the TA,
while the remaining hosts prove identity using values provided
by a trusted host and certificate trails that end on that host.
The name of a trusted host is also the name of its sugroup
and also the subject and issuer name on its trusted certificate.
The TA is not necessarily a trusted host in this sense, but often is.
.Pp
In some schemes there are separate keys for servers and clients.
A server can also be a client of another server,
but a client can never be a server for another client.
In general, trusted hosts and nontrusted hosts that operate
as both server and client have parameter files that contain
both server and client keys. Hosts that operate
only as clients have key files that contain only client keys.
.Pp
The PC scheme supports only one trusted host in the group.
On trusted host alice run
.Nm
.Fl P
.Fl p Ar password
to generate the host key file
.Pa ntpkey_RSAkey_ Ns Ar alice.filestamp
and trusted private certificate file
.Pa ntpkey_RSA-MD5_cert_ Ns Ar alice.filestamp .
Copy both files to all group hosts;
they replace the files which would be generated in other schemes.
On each host bob install a soft link from the generic name
.Pa ntpkey_host_ Ns Ar bob
to the host key file and soft link
.Pa ntpkey_cert_ Ns Ar bob
to the private certificate file.
Note the generic links are on bob, but point to files generated
by trusted host alice. In this scheme it is not possible to refresh
either the keys or certificates without copying them
to all other hosts in the group.
.Pp
For the IFF scheme proceed as in the TC scheme to generate keys
and certificates for all group hosts, then for every trusted host in the group,
generate the IFF parameter file.
On trusted host alice run
.Nm
.Fl T
.Fl I
.Fl p Ar password
to produce her parameter file
.Pa ntpkey_IFFpar_ Ns Ar alice.filestamp ,
which includes both server and client keys.
Copy this file to all group hosts that operate as both servers
and clients and install a soft link from the generic
.Pa ntpkey_iff_ Ns Ar alice
to this file.
If there are no hosts restricted to operate only as clients,
there is nothing further to do. As the IFF scheme is independent
of keys and certificates, these files can be refreshed as needed.
.Pp
If a rogue client has the parameter file, it could masquerade
as a legitimate server and present a middleman threat.
To eliminate this threat, the client keys can be extracted
from the parameter file and distributed to all restricted clients.
After generating the parameter file, on alice run
.Nm
.Fl e
and pipe the output to a file or mail program.
Copy or mail this file to all restricted clients.
On these clients install a soft link from the generic
.Pa ntpkey_iff_ Ns Ar alice
to this file. To further protect the integrity of the keys,
each file can be encrypted with a secret password.
.Pp
For the GQ scheme proceed as in the TC scheme to generate keys
and certificates for all group hosts, then for every trusted host
in the group, generate the IFF parameter file.
On trusted host alice run
.Nm
.Fl T
.Fl G
.Fl p Ar password
to produce her parameter file
.Pa ntpkey_GQpar_ Ns Ar alice.filestamp ,
which includes both server and client keys.
Copy this file to all group hosts and install a soft link
from the generic
.Pa ntpkey_gq_ Ns Ar alice
to this file.
In addition, on each host bob install a soft link
from generic
.Pa ntpkey_gq_ Ns Ar bob
to this file.
As the GQ scheme updates the GQ parameters file and certificate
at the same time, keys and certificates can be regenerated as needed.
.Pp
For the MV scheme, proceed as in the TC scheme to generate keys
and certificates for all group hosts.
For illustration assume trish is the TA, alice one of several trusted hosts
and bob one of her clients. On TA trish run
.Nm
.Fl V Ar n
.Fl p Ar password ,
where
.Ar n
is the number of revokable keys (typically 5) to produce
the parameter file
.Pa ntpkeys_MVpar_ Ns Ar trish.filestamp
and client key files
.Pa ntpkeys_MVkeyd_ Ns Ar trish.filestamp
where
.Ar d
is the key number (0 \&<
.Ar d
\&<
.Ar n ) .
Copy the parameter file to alice and install a soft link
from the generic
.Pa ntpkey_mv_ Ns Ar alice
to this file.
Copy one of the client key files to alice for later distribution
to her clients.
It doesn't matter which client key file goes to alice,
since they all work the same way.
Alice copies the client key file to all of her cliens.
On client bob install a soft link from generic
.Pa ntpkey_mvkey_ Ns Ar bob
to the client key file.
As the MV scheme is independent of keys and certificates,
these files can be refreshed as needed.
.Ss Command Line Options
.Bl -tag -width indent
.It Fl c Oo Cm RSA-MD2 | RSA-MD5 | RSA-SHA | RSA-SHA1 | RSA-MDC2 | RSA-RIPEMD160 | DSA-SHA | DSA-SHA1 Oc
Select certificate message digest/signature encryption scheme.
Note that RSA schemes must be used with a RSA sign key and DSA
schemes must be used with a DSA sign key.
The default without this option is
.Cm RSA-MD5 .
.It Fl d
Enable debugging.
This option displays the cryptographic data produced in eye-friendly billboards.
.It Fl e
Write the IFF client keys to the standard output.
This is intended for automatic key distribution by mail.
.It Fl G
Generate parameters and keys for the GQ identification scheme,
obsoleting any that may exist.
.It Fl g
Generate keys for the GQ identification scheme
using the existing GQ parameters.
If the GQ parameters do not yet exist, create them first.
.It Fl H
Generate new host keys, obsoleting any that may exist.
.It Fl I
Generate parameters for the IFF identification scheme,
obsoleting any that may exist.
.It Fl i Ar name
Set the suject name to
.Ar name .
This is used as the subject field in certificates
and in the file name for host and sign keys.
.It Fl M
Generate MD5 keys, obsoleting any that may exist.
.It Fl P
Generate a private certificate.
By default, the program generates public certificates.
.It Fl p Ar password
Encrypt generated files containing private data with
.Ar password
and the DES-CBC algorithm.
.It Fl q
Set the password for reading files to password.
.It Fl S Oo Cm RSA | DSA Oc
Generate a new sign key of the designated type,
obsoleting any that may exist.
By default, the program uses the host key as the sign key.
.It Fl s Ar name
Set the issuer name to
.Ar name .
This is used for the issuer field in certificates
and in the file name for identity files.
.It Fl T
Generate a trusted certificate.
By default, the program generates a non-trusted certificate.
.It Fl V Ar nkeys
Generate parameters and keys for the Mu-Varadharajan (MV) identification scheme.
.El
.Ss Random Seed File
All cryptographically sound key generation schemes must have means
to randomize the entropy seed used to initialize
the internal pseudo-random number generator used
by the library routines.
The OpenSSL library uses a designated random seed file for this purpose.
The file must be available when starting the NTP daemon and
.Nm
program. If a site supports OpenSSL or its companion OpenSSH,
it is very likely that means to do this are already available.
.Pp
It is important to understand that entropy must be evolved
for each generation, for otherwise the random number sequence
would be predictable.
Various means dependent on external events, such as keystroke intervals,
can be used to do this and some systems have built-in entropy sources.
Suitable means are described in the OpenSSL software documentation,
but are outside the scope of this page.
.Pp
The entropy seed used by the OpenSSL library is contained in a file,
usually called
.Cm .rnd ,
which must be available when starting the NTP daemon
or the
.Nm
program. The NTP daemon will first look for the file
using the path specified by the
.Ic randfile
subcommand of the
.Ic crypto
configuration command.
If not specified in this way, or when starting the
.Nm
program,
the OpenSSL library will look for the file using the path specified
by the
.Ev RANDFILE
environment variable in the user home directory,
whether root or some other user.
If the
.Ev RANDFILE
environment variable is not present,
the library will look for the
.Cm .rnd
file in the user home directory.
If the file is not available or cannot be written,
the daemon exits with a message to the system log and the program
exits with a suitable error message.
.Ss Cryptographic Data Files
All other file formats begin with two lines.
The first contains the file name, including the generated host name
and filestamp.
The second contains the datestamp in conventional Unix date format.
Lines beginning with # are considered comments and ignored by the
.Nm
program and
.Xr ntpd 8
daemon.
Cryptographic values are encoded first using ASN.1 rules,
then encrypted if necessary, and finally written PEM-encoded
printable ASCII format preceded and followed by MIME content identifier lines.
.Pp
The format of the symmetric keys file is somewhat different
than the other files in the interest of backward compatibility.
Since DES-CBC is deprecated in NTPv4, the only key format of interest
is MD5 alphanumeric strings. Following hte heard the keys are
entered one per line in the format
.D1 Ar keyno type key
where
.Ar keyno
is a positive integer in the range 1-65,535,
.Ar type
is the string MD5 defining the key format and
.Ar key
is the key itself,
which is a printable ASCII string 16 characters or less in length.
Each character is chosen from the 93 printable characters
in the range 0x21 through 0x7f excluding space and the
.Ql #
character.
.Pp
Note that the keys used by the
.Xr ntpq 8
and
.Xr ntpdc 8
programs
are checked against passwords requested by the programs
and entered by hand, so it is generally appropriate to specify these keys
in human readable ASCII format.
.Pp
The
.Nm
program generates a MD5 symmetric keys file
.Pa ntpkey_MD5key_ Ns Ar hostname.filestamp .
Since the file contains private shared keys,
it should be visible only to root and distributed by secure means
to other subnet hosts.
The NTP daemon loads the file
.Pa ntp.keys ,
so
.Nm
installs a soft link from this name to the generated file.
Subsequently, similar soft links must be installed by manual
or automated means on the other subnet hosts.
While this file is not used with the Autokey Version 2 protocol,
it is needed to authenticate some remote configuration commands
used by the
.Xr ntpq 8
and
.Xr ntpdc 8
utilities.
.Sh Bugs
It can take quite a while to generate some cryptographic values,
from one to several minutes with modern architectures
such as UltraSPARC and up to tens of minutes to an hour
with older architectures such as SPARC IPC.