mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-27 21:02:38 +08:00
Update to FreeBSD 9.3
This commit is contained in:
parent
948b1a5b57
commit
7eeb079d84
@ -1 +1 @@
|
||||
Subproject commit 74d8320d56de778817fa39bc074b177c93945481
|
||||
Subproject commit a5feb686027eafe7ae45360846ff5ae4cd64fed7
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)auth.h 1.17 88/02/08 SMI
|
||||
* from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */
|
||||
/* $FreeBSD$ */
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC
|
||||
* from: @(#)auth_des.h 1.14 94/04/25 SMI
|
||||
|
@ -1,30 +1,29 @@
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)auth_unix.h 1.8 88/02/08 SMI
|
||||
* from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC
|
||||
|
@ -1,49 +1,31 @@
|
||||
/* $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* The contents of this file are subject to the Sun Standards
|
||||
* License Version 1.0 the (the "License";) You may not use
|
||||
* this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at lib/libc/rpc/LICENSE
|
||||
/*-
|
||||
* Copyright (c) 2010, Oracle America, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Software distributed under the License is distributed on
|
||||
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||
* express or implied. See the License for the specific
|
||||
* language governing rights and limitations under the License.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the "Oracle America, Inc." nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* The Original Code is Copyright 1998 by Sun Microsystems, Inc
|
||||
*
|
||||
* The Initial Developer of the Original Code is: Sun
|
||||
* Microsystems, Inc.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clnt.h 1.31 94/04/29 SMI
|
||||
* from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC
|
||||
@ -52,9 +34,6 @@
|
||||
|
||||
/*
|
||||
* clnt.h - Client side remote procedure call interface.
|
||||
*
|
||||
* Copyright (c) 1986-1991,1994-1999 by Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _RPC_CLNT_H_
|
||||
|
@ -1,33 +1,32 @@
|
||||
/* $NetBSD: clnt_soc.h,v 1.1 2000/06/02 22:57:55 fvdl Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: pmap_clnt.h,v 1.9 2000/06/02 22:57:55 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
|
||||
* from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: pmap_prot.h,v 1.8 2000/06/02 22:57:55 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)pmap_prot.h 1.14 88/02/08 SMI
|
||||
* from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: rpc.h,v 1.13 2000/06/02 22:57:56 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)rpc.h 1.9 88/02/08 SMI
|
||||
* from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: rpc_msg.h,v 1.11 2000/06/02 22:57:56 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)rpc_msg.h 1.7 86/07/16 SMI
|
||||
* from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC
|
||||
|
@ -1,33 +1,32 @@
|
||||
/* $NetBSD: rpcb_clnt.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
|
@ -1,32 +1,31 @@
|
||||
%/*
|
||||
%/*-
|
||||
% * $FreeBSD$
|
||||
% *
|
||||
% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
% * unrestricted use provided that this legend is included on all tape
|
||||
% * media and as a part of the software program in whole or part. Users
|
||||
% * may copy or modify Sun RPC without charge, but are not authorized
|
||||
% * to license or distribute it to anyone else except as part of a product or
|
||||
% * program developed by the user.
|
||||
% * Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
% * All rights reserved.
|
||||
% *
|
||||
% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
% * Redistribution and use in source and binary forms, with or without
|
||||
% * modification, are permitted provided that the following conditions are met:
|
||||
% * - Redistributions of source code must retain the above copyright notice,
|
||||
% * this list of conditions and the following disclaimer.
|
||||
% * - 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.
|
||||
% * - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
% * contributors may be used to endorse or promote products derived
|
||||
% * from this software without specific prior written permission.
|
||||
% *
|
||||
% * Sun RPC is provided with no support and without any obligation on the
|
||||
% * part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
% * modification or enhancement.
|
||||
% *
|
||||
% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
% * OR ANY PART THEREOF.
|
||||
% *
|
||||
% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
% * or profits or other special, indirect and consequential damages, even if
|
||||
% * Sun has been advised of the possibility of such damages.
|
||||
% *
|
||||
% * Sun Microsystems, Inc.
|
||||
% * 2550 Garcia Avenue
|
||||
% * Mountain View, California 94043
|
||||
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
% */
|
||||
%/*
|
||||
% * Copyright (c) 1988 by Sun Microsystems, Inc.
|
||||
|
@ -1,33 +1,32 @@
|
||||
/* $NetBSD: rpcent.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: svc.h,v 1.17 2000/06/02 22:57:56 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)svc.h 1.35 88/12/17 SMI
|
||||
* from: @(#)svc.h 1.27 94/04/25 SMI
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: svc_auth.h,v 1.8 2000/06/02 22:57:57 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)svc_auth.h 1.6 86/07/16 SMI
|
||||
* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
|
||||
|
@ -1,33 +1,32 @@
|
||||
/* $NetBSD: svc_soc.h,v 1.1 2000/06/02 22:57:57 fvdl Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
/*-
|
||||
* Copyright (c) 2009, Sun Microsystems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of Sun Microsystems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)xdr.h 1.19 87/04/22 SMI
|
||||
* from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
|
||||
|
@ -64,12 +64,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if_types.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/queue.h>
|
||||
#ifdef INET6
|
||||
#include <net/if_var.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet6/in6_var.h> /* XXX */
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
@ -246,6 +249,9 @@ static int get_portmatch(const struct addrinfo *, const char *);
|
||||
static int get_port(struct addrinfo *, const char *, int);
|
||||
static const struct afd *find_afd(int);
|
||||
static int addrconfig(struct addrinfo *);
|
||||
#ifdef INET6
|
||||
static int is_ifdisabled(char *);
|
||||
#endif
|
||||
static void set_source(struct ai_order *, struct policyhead *);
|
||||
static int comp_dst(const void *, const void *);
|
||||
#ifdef INET6
|
||||
@ -1003,7 +1009,8 @@ comp_dst(const void *arg1, const void *arg2)
|
||||
* We compare the match length in a same AF only.
|
||||
*/
|
||||
if (dst1->aio_ai->ai_addr->sa_family ==
|
||||
dst2->aio_ai->ai_addr->sa_family) {
|
||||
dst2->aio_ai->ai_addr->sa_family &&
|
||||
dst1->aio_ai->ai_addr->sa_family != AF_INET) {
|
||||
if (dst1->aio_matchlen > dst2->aio_matchlen) {
|
||||
return(-1);
|
||||
}
|
||||
@ -1522,10 +1529,11 @@ find_afd(int af)
|
||||
}
|
||||
|
||||
/*
|
||||
* post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
|
||||
* will take care of it.
|
||||
* the semantics of AI_ADDRCONFIG is not defined well. we are not sure
|
||||
* if the code is right or not.
|
||||
* RFC 3493: AI_ADDRCONFIG check. Determines which address families are
|
||||
* configured on the local system and correlates with pai->ai_family value.
|
||||
* If an address family is not configured on the system, it will not be
|
||||
* queried for. For this purpose, loopback addresses are not considered
|
||||
* configured addresses.
|
||||
*
|
||||
* XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
|
||||
* _dns_getaddrinfo.
|
||||
@ -1533,37 +1541,80 @@ find_afd(int af)
|
||||
static int
|
||||
addrconfig(struct addrinfo *pai)
|
||||
{
|
||||
int s, af;
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
struct sockaddr_in *sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
int seen_inet = 0, seen_inet6 = 0;
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Note that implementation dependent test for address
|
||||
* configuration should be done everytime called
|
||||
* (or apropriate interval),
|
||||
* because addresses will be dynamically assigned or deleted.
|
||||
*/
|
||||
af = pai->ai_family;
|
||||
if (af == AF_UNSPEC) {
|
||||
if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
||||
af = AF_INET;
|
||||
else {
|
||||
_close(s);
|
||||
if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
af = AF_INET6;
|
||||
else
|
||||
_close(s);
|
||||
if (getifaddrs(&ifaddrs) != 0)
|
||||
return (0);
|
||||
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_UP) == 0)
|
||||
continue;
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
if (seen_inet)
|
||||
continue;
|
||||
sin = (struct sockaddr_in *)(ifa->ifa_addr);
|
||||
if (IN_LOOPBACK(htonl(sin->sin_addr.s_addr)))
|
||||
continue;
|
||||
seen_inet = 1;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (seen_inet6)
|
||||
continue;
|
||||
sin6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
|
||||
if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
||||
continue;
|
||||
if ((ifa->ifa_flags & IFT_LOOP) != 0 &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
|
||||
continue;
|
||||
if (is_ifdisabled(ifa->ifa_name))
|
||||
continue;
|
||||
seen_inet6 = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (af != AF_UNSPEC) {
|
||||
if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
|
||||
return 0;
|
||||
_close(s);
|
||||
freeifaddrs(ifaddrs);
|
||||
|
||||
switch(pai->ai_family) {
|
||||
case AF_INET6:
|
||||
return (seen_inet6);
|
||||
case AF_INET:
|
||||
return (seen_inet);
|
||||
case AF_UNSPEC:
|
||||
if (seen_inet == seen_inet6)
|
||||
return (seen_inet);
|
||||
pai->ai_family = seen_inet ? AF_INET : AF_INET6;
|
||||
return (1);
|
||||
}
|
||||
pai->ai_family = af;
|
||||
return 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static int
|
||||
is_ifdisabled(char *name)
|
||||
{
|
||||
struct in6_ndireq nd;
|
||||
int fd;
|
||||
|
||||
if ((fd = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
||||
return (-1);
|
||||
memset(&nd, 0, sizeof(nd));
|
||||
strlcpy(nd.ifname, name, sizeof(nd.ifname));
|
||||
if (_ioctl(fd, SIOCGIFINFO_IN6, &nd) < 0) {
|
||||
_close(fd);
|
||||
return (-1);
|
||||
}
|
||||
_close(fd);
|
||||
return ((nd.ndi.flags & ND6_IFF_IFDISABLED) != 0);
|
||||
}
|
||||
|
||||
/* convert a string to a scope identifier. XXX: IPv6 specific */
|
||||
static int
|
||||
ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
|
||||
|
@ -201,6 +201,7 @@ ipsec_dump_ipsecrequest(buf, len, xisr, bound)
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
proto = "tcp";
|
||||
break;
|
||||
default:
|
||||
__ipsec_errcode = EIPSEC_INVAL_PROTO;
|
||||
return NULL;
|
||||
|
@ -106,8 +106,7 @@ in_getaddr(const char *s, int which)
|
||||
struct netent *np;
|
||||
|
||||
sin->sin_len = sizeof(*sin);
|
||||
if (which != MASK)
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_family = AF_INET;
|
||||
|
||||
if (which == ADDR) {
|
||||
char *p = NULL;
|
||||
@ -126,6 +125,7 @@ in_getaddr(const char *s, int which)
|
||||
*p = '/';
|
||||
errx(1, "%s: bad value (width %s)", s, errstr);
|
||||
}
|
||||
min->sin_family = AF_INET;
|
||||
min->sin_len = sizeof(*min);
|
||||
min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
|
||||
0xffffffff);
|
||||
|
@ -62,7 +62,7 @@ setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
|
||||
|
||||
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
|
||||
errx(1, "setifgroup: group name too long");
|
||||
if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1)
|
||||
if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
|
||||
err(1," SIOCAIFGROUP");
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
|
||||
|
||||
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
|
||||
errx(1, "unsetifgroup: group name too long");
|
||||
if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1)
|
||||
if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
|
||||
err(1, "SIOCDIFGROUP");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
# @(#)keywords 8.2 (Berkeley) 3/19/94
|
||||
# $FreeBSD$
|
||||
|
||||
4
|
||||
6
|
||||
add
|
||||
atalk
|
||||
blackhole
|
||||
|
@ -177,7 +177,7 @@ usage(const char *cp)
|
||||
if (cp != NULL)
|
||||
warnx("bad keyword: %s", cp);
|
||||
(void) fprintf(stderr,
|
||||
"usage: route [-dnqtv] command [[modifiers] args]\n");
|
||||
"usage: route [-46dnqtv] command [[modifiers] args]\n");
|
||||
exit(EX_USAGE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@ -263,8 +263,24 @@ main(int argc, char **argv)
|
||||
if (argc < 2)
|
||||
usage(NULL);
|
||||
|
||||
while ((ch = getopt(argc, argv, "nqdtv")) != -1)
|
||||
while ((ch = getopt(argc, argv, "46nqdtv")) != -1)
|
||||
switch(ch) {
|
||||
case '4':
|
||||
#ifdef INET
|
||||
c->af = AF_INET;
|
||||
c->aflen = sizeof(struct sockaddr_in);
|
||||
#else
|
||||
errx(1, "IPv4 support is not compiled in");
|
||||
#endif
|
||||
break;
|
||||
case '6':
|
||||
#ifdef INET6
|
||||
c->af = AF_INET6;
|
||||
c->aflen = sizeof(struct sockaddr_in6);
|
||||
#else
|
||||
errx(1, "IPv6 support is not compiled in");
|
||||
#endif
|
||||
break;
|
||||
case 'n':
|
||||
c->nflag = 1;
|
||||
break;
|
||||
@ -485,10 +501,12 @@ flushroutes(struct rt_ctx *c, int argc, char *argv[])
|
||||
if (**argv != '-')
|
||||
usage(*argv);
|
||||
switch (keyword(*argv + 1)) {
|
||||
case K_4:
|
||||
case K_INET:
|
||||
c->af = AF_INET;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case K_6:
|
||||
case K_INET6:
|
||||
c->af = AF_INET6;
|
||||
break;
|
||||
@ -903,11 +921,13 @@ newroute(struct rt_ctx *c, int argc, char **argv)
|
||||
c->af = AF_LINK;
|
||||
c->aflen = sizeof(struct sockaddr_dl);
|
||||
break;
|
||||
case K_4:
|
||||
case K_INET:
|
||||
c->af = AF_INET;
|
||||
c->aflen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case K_6:
|
||||
case K_INET6:
|
||||
c->af = AF_INET6;
|
||||
c->aflen = sizeof(struct sockaddr_in6);
|
||||
|
@ -109,6 +109,7 @@ int ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb);
|
||||
int ata_res_sbuf(struct ccb_ataio *ataio, struct sbuf *sb);
|
||||
|
||||
void ata_print_ident(struct ata_params *ident_data);
|
||||
void ata_print_ident_short(struct ata_params *ident_data);
|
||||
|
||||
uint32_t ata_logical_sector_size(struct ata_params *ident_data);
|
||||
uint64_t ata_physical_sector_size(struct ata_params *ident_data);
|
||||
@ -143,6 +144,7 @@ int ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
|
||||
void semb_print_ident(struct sep_identify_data *ident_data);
|
||||
void semb_print_ident_short(struct sep_identify_data *ident_data);
|
||||
|
||||
void semb_receive_diagnostic_results(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
|
@ -84,15 +84,15 @@ typedef struct {
|
||||
#define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80)
|
||||
#define CAM_PRIORITY_XPT ((CAM_RL_XPT << 8) + 0x80)
|
||||
#define CAM_PRIORITY_DEV ((CAM_RL_DEV << 8) + 0x80)
|
||||
#define CAM_PRIORITY_OOB (CAM_RL_DEV << 8)
|
||||
#define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80)
|
||||
#define CAM_PRIORITY_NONE (u_int32_t)-1
|
||||
#define CAM_PRIORITY_TO_RL(x) ((x) >> 8)
|
||||
#define CAM_RL_TO_PRIORITY(x) ((x) << 8)
|
||||
u_int32_t generation;
|
||||
int index;
|
||||
#define CAM_UNQUEUED_INDEX -1
|
||||
#define CAM_ACTIVE_INDEX -2
|
||||
#define CAM_DONEQ_INDEX -3
|
||||
#define CAM_EXTRAQ_INDEX INT_MAX
|
||||
} cam_pinfo;
|
||||
|
||||
/*
|
||||
|
@ -154,8 +154,6 @@ typedef enum {
|
||||
/* Path statistics (error counts, etc.) */
|
||||
XPT_GDEV_STATS = 0x0c,
|
||||
/* Device statistics (error counts, etc.) */
|
||||
XPT_FREEZE_QUEUE = 0x0d,
|
||||
/* Freeze device queue */
|
||||
XPT_DEV_ADVINFO = 0x0e,
|
||||
/* Get/Set Device advanced information */
|
||||
/* SCSI Control Functions: 0x10->0x1F */
|
||||
@ -592,6 +590,7 @@ typedef enum {
|
||||
PIM_NO_6_BYTE = 0x08, /* Do not send 6-byte commands */
|
||||
PIM_SEQSCAN = 0x04, /* Do bus scans sequentially, not in parallel */
|
||||
PIM_UNMAPPED = 0x02,
|
||||
PIM_NOSCAN = 0x01 /* SIM does its own scanning */
|
||||
} pi_miscflag;
|
||||
|
||||
/* Path Inquiry CCB */
|
||||
@ -774,7 +773,6 @@ struct ccb_relsim {
|
||||
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
|
||||
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
|
||||
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08
|
||||
#define RELSIM_RELEASE_RUNLEVEL 0x10
|
||||
u_int32_t openings;
|
||||
u_int32_t release_timeout; /* Abstract argument. */
|
||||
u_int32_t qfrozen_cnt;
|
||||
@ -1328,6 +1326,19 @@ cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
|
||||
smpio->smp_response_len = smp_response_len;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_set_ccbstatus(union ccb *ccb, cam_status status)
|
||||
{
|
||||
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
|
||||
ccb->ccb_h.status |= status;
|
||||
}
|
||||
|
||||
static __inline cam_status
|
||||
cam_ccb_status(union ccb *ccb)
|
||||
{
|
||||
return ((cam_status)(ccb->ccb_h.status & CAM_STATUS_MASK));
|
||||
}
|
||||
|
||||
void cam_calc_geometry(struct ccb_calc_geometry *ccg, int extended);
|
||||
|
||||
__END_DECLS
|
||||
|
@ -61,13 +61,13 @@ typedef enum {
|
||||
#endif
|
||||
|
||||
#ifndef CAM_DEBUG_BUS
|
||||
#define CAM_DEBUG_BUS (-1)
|
||||
#define CAM_DEBUG_BUS CAM_BUS_WILDCARD
|
||||
#endif
|
||||
#ifndef CAM_DEBUG_TARGET
|
||||
#define CAM_DEBUG_TARGET (-1)
|
||||
#define CAM_DEBUG_TARGET CAM_TARGET_WILDCARD
|
||||
#endif
|
||||
#ifndef CAM_DEBUG_LUN
|
||||
#define CAM_DEBUG_LUN (-1)
|
||||
#define CAM_DEBUG_LUN CAM_LUN_WILDCARD
|
||||
#endif
|
||||
|
||||
#ifndef CAM_DEBUG_DELAY
|
||||
@ -99,6 +99,17 @@ extern u_int32_t cam_debug_delay;
|
||||
DELAY(cam_debug_delay); \
|
||||
}
|
||||
|
||||
#define CAM_DEBUG_DEV(dev, flag, printfargs) \
|
||||
if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \
|
||||
&& (cam_dpath != NULL) \
|
||||
&& (xpt_path_comp_dev(cam_dpath, dev) >= 0) \
|
||||
&& (xpt_path_comp_dev(cam_dpath, dev) < 2)) { \
|
||||
xpt_print_device(dev); \
|
||||
printf printfargs; \
|
||||
if (cam_debug_delay != 0) \
|
||||
DELAY(cam_debug_delay); \
|
||||
}
|
||||
|
||||
#define CAM_DEBUG_PRINT(flag, printfargs) \
|
||||
if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \
|
||||
printf("cam_debug: "); \
|
||||
|
@ -121,6 +121,7 @@ struct cam_periph {
|
||||
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
|
||||
#define CAM_PERIPH_RECOVERY_INPROG 0x20
|
||||
#define CAM_PERIPH_FREE 0x80
|
||||
#define CAM_PERIPH_ANNOUNCED 0x100
|
||||
u_int32_t immediate_priority;
|
||||
u_int32_t refcount;
|
||||
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
|
||||
@ -171,8 +172,6 @@ int cam_periph_ioctl(struct cam_periph *periph, u_long cmd,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags));
|
||||
void cam_freeze_devq(struct cam_path *path);
|
||||
void cam_freeze_devq_arg(struct cam_path *path, u_int32_t flags,
|
||||
uint32_t arg);
|
||||
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
|
||||
u_int32_t opening_reduction, u_int32_t arg,
|
||||
int getcount_only);
|
||||
|
@ -35,6 +35,7 @@
|
||||
/* Forward Declarations */
|
||||
union ccb;
|
||||
struct cam_periph;
|
||||
struct cam_ed;
|
||||
struct cam_sim;
|
||||
|
||||
/*
|
||||
@ -89,7 +90,10 @@ void xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
|
||||
uint32_t *device_ref);
|
||||
int xpt_path_comp(struct cam_path *path1,
|
||||
struct cam_path *path2);
|
||||
int xpt_path_comp_dev(struct cam_path *path,
|
||||
struct cam_ed *dev);
|
||||
void xpt_print_path(struct cam_path *path);
|
||||
void xpt_print_device(struct cam_ed *device);
|
||||
void xpt_print(struct cam_path *path, const char *fmt, ...);
|
||||
int xpt_path_string(struct cam_path *path, char *str,
|
||||
size_t str_len);
|
||||
|
@ -47,12 +47,8 @@ u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
|
||||
#else /* __rtems__ */
|
||||
#define xpt_freeze_devq(path, count) do { } while (0)
|
||||
#endif /* __rtems__ */
|
||||
u_int32_t xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl,
|
||||
u_int count);
|
||||
void xpt_release_devq(struct cam_path *path,
|
||||
u_int count, int run_queue);
|
||||
void xpt_release_devq_rl(struct cam_path *path, cam_rl rl,
|
||||
u_int count, int run_queue);
|
||||
int xpt_sim_opened(struct cam_sim *sim);
|
||||
void xpt_done(union ccb *done_ccb);
|
||||
void xpt_batch_start(struct cam_sim *sim);
|
||||
|
@ -672,6 +672,10 @@ scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
|
||||
if (pd_type == T_RBC)
|
||||
pd_type = T_DIRECT;
|
||||
|
||||
/* Map NODEVICE to Direct Access Device to handle REPORT LUNS, etc. */
|
||||
if (pd_type == T_NODEVICE)
|
||||
pd_type = T_DIRECT;
|
||||
|
||||
opmask = 1 << pd_type;
|
||||
|
||||
for (j = 0; j < num_tables; j++) {
|
||||
@ -1121,7 +1125,7 @@ static struct asc_table_entry asc_table[] = {
|
||||
{ SST(0x04, 0x10, SS_RDEF, /* XXX TBD */
|
||||
"Logical unit not ready, auxiliary memory not accessible") },
|
||||
/* DT WRO AEB VF */
|
||||
{ SST(0x04, 0x11, SS_RDEF, /* XXX TBD */
|
||||
{ SST(0x04, 0x11, SS_TUR | SSQ_MANY | SSQ_DECREMENT_COUNT | EBUSY,
|
||||
"Logical unit not ready, notify (enable spinup) required") },
|
||||
/* M V */
|
||||
{ SST(0x04, 0x12, SS_RDEF, /* XXX TBD */
|
||||
@ -1652,7 +1656,7 @@ static struct asc_table_entry asc_table[] = {
|
||||
{ SST(0x24, 0x08, SS_RDEF, /* XXX TBD */
|
||||
"Invalid XCDB") },
|
||||
/* DTLPWROMAEBKVF */
|
||||
{ SST(0x25, 0x00, SS_FATAL | ENXIO,
|
||||
{ SST(0x25, 0x00, SS_FATAL | ENXIO | SSQ_LOST,
|
||||
"Logical unit not supported") },
|
||||
/* DTLPWROMAEBKVF */
|
||||
{ SST(0x26, 0x00, SS_FATAL | EINVAL,
|
||||
@ -2170,7 +2174,7 @@ static struct asc_table_entry asc_table[] = {
|
||||
{ SST(0x3F, 0x0D, SS_RDEF,
|
||||
"Volume set reassigned") },
|
||||
/* DTLPWROMAE */
|
||||
{ SST(0x3F, 0x0E, SS_RDEF, /* XXX TBD */
|
||||
{ SST(0x3F, 0x0E, SS_RDEF | SSQ_RESCAN ,
|
||||
"Reported LUNs data has changed") },
|
||||
/* DTLPWROMAEBKVF */
|
||||
{ SST(0x3F, 0x0F, SS_RDEF, /* XXX TBD */
|
||||
@ -3270,6 +3274,7 @@ scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
|
||||
action |= SS_RETRY|SSQ_DECREMENT_COUNT|
|
||||
SSQ_PRINT_SENSE;
|
||||
}
|
||||
action |= SSQ_UA;
|
||||
}
|
||||
}
|
||||
if ((action & SS_MASK) >= SS_START &&
|
||||
@ -5256,6 +5261,21 @@ scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
|
||||
dtype, rstr, qtype);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data)
|
||||
{
|
||||
char vendor[16], product[48], revision[16];
|
||||
|
||||
cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
|
||||
sizeof(vendor));
|
||||
cam_strvis(product, inq_data->product, sizeof(inq_data->product),
|
||||
sizeof(product));
|
||||
cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
|
||||
sizeof(revision));
|
||||
|
||||
printf("<%s %s %s>", vendor, product, revision);
|
||||
}
|
||||
|
||||
#ifndef __rtems__
|
||||
/*
|
||||
* Table of syncrates that don't follow the "divisible by 4"
|
||||
@ -6510,7 +6530,11 @@ scsi_devid_match(uint8_t *lhs, size_t lhs_len, uint8_t *rhs, size_t rhs_len)
|
||||
while (rhs_id <= rhs_last
|
||||
&& (rhs_id->identifier + rhs_id->length) <= rhs_end) {
|
||||
|
||||
if (rhs_id->length == lhs_id->length
|
||||
if ((rhs_id->id_type &
|
||||
(SVPD_ID_ASSOC_MASK | SVPD_ID_TYPE_MASK)) ==
|
||||
(lhs_id->id_type &
|
||||
(SVPD_ID_ASSOC_MASK | SVPD_ID_TYPE_MASK))
|
||||
&& rhs_id->length == lhs_id->length
|
||||
&& memcmp(rhs_id->identifier, lhs_id->identifier,
|
||||
rhs_id->length) == 0)
|
||||
return (0);
|
||||
|
@ -88,6 +88,9 @@ typedef enum {
|
||||
* and text.
|
||||
*/
|
||||
SSQ_PRINT_SENSE = 0x0800,
|
||||
SSQ_UA = 0x1000, /* Broadcast UA. */
|
||||
SSQ_RESCAN = 0x2000, /* Rescan target for LUNs. */
|
||||
SSQ_LOST = 0x4000, /* Destroy the LUNs. */
|
||||
SSQ_MASK = 0xff00
|
||||
} scsi_sense_action_qualifier;
|
||||
|
||||
@ -2309,6 +2312,7 @@ char * scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string,
|
||||
size_t len);
|
||||
|
||||
void scsi_print_inquiry(struct scsi_inquiry_data *inq_data);
|
||||
void scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data);
|
||||
|
||||
u_int scsi_calc_syncsrate(u_int period_factor);
|
||||
u_int scsi_calc_syncparam(u_int period);
|
||||
|
@ -116,6 +116,31 @@ struct scsi_read_defect_data_10
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_sanitize
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte2;
|
||||
#define SSZ_SERVICE_ACTION_OVERWRITE 0x01
|
||||
#define SSZ_SERVICE_ACTION_BLOCK_ERASE 0x02
|
||||
#define SSZ_SERVICE_ACTION_CRYPTO_ERASE 0x03
|
||||
#define SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE 0x1F
|
||||
#define SSZ_UNRESTRICTED_EXIT 0x20
|
||||
#define SSZ_IMMED 0x80
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t length[2];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_sanitize_parameter_list
|
||||
{
|
||||
u_int8_t byte1;
|
||||
#define SSZPL_INVERT 0x80
|
||||
u_int8_t reserved;
|
||||
u_int8_t length[2];
|
||||
/* Variable length initialization pattern. */
|
||||
#define SSZPL_MAX_PATTERN_LENGTH 65535
|
||||
};
|
||||
|
||||
struct scsi_read_defect_data_12
|
||||
{
|
||||
u_int8_t opcode;
|
||||
@ -156,6 +181,7 @@ struct scsi_read_defect_data_12
|
||||
#define WRITE_AND_VERIFY 0x2e
|
||||
#define VERIFY 0x2f
|
||||
#define READ_DEFECT_DATA_10 0x37
|
||||
#define SANITIZE 0x48
|
||||
#define READ_DEFECT_DATA_12 0xb7
|
||||
|
||||
struct format_defect_list_header
|
||||
@ -508,6 +534,12 @@ void scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len,
|
||||
u_int8_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_sanitize(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int8_t byte2, u_int16_t control,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
#endif /* !_KERNEL */
|
||||
__END_DECLS
|
||||
|
||||
|
@ -167,8 +167,8 @@ struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
|
||||
struct pf_addr *, u_int16_t, struct pf_addr *,
|
||||
u_int16_t, int);
|
||||
int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
|
||||
struct pf_addr *, struct pf_addr *, u_int16_t,
|
||||
struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
|
||||
struct pf_addr *, uint16_t, struct pf_addr *, uint16_t,
|
||||
struct pf_addr *, uint16_t*, uint16_t, uint16_t,
|
||||
struct pf_src_node **);
|
||||
|
||||
#define mix(a,b,c) \
|
||||
@ -320,13 +320,13 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
|
||||
|
||||
int
|
||||
pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
|
||||
struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
|
||||
struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
|
||||
struct pf_src_node **sn)
|
||||
struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
|
||||
uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low,
|
||||
uint16_t high, struct pf_src_node **sn)
|
||||
{
|
||||
struct pf_state_key_cmp key;
|
||||
struct pf_addr init_addr;
|
||||
u_int16_t cut;
|
||||
uint16_t cut;
|
||||
|
||||
bzero(&init_addr, sizeof(init_addr));
|
||||
if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
|
||||
@ -337,34 +337,38 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
|
||||
high = 65535;
|
||||
}
|
||||
|
||||
bzero(&key,sizeof(key));
|
||||
key.af = af;
|
||||
key.proto = proto;
|
||||
key.port[0] = dport;
|
||||
PF_ACPY(&key.addr[0], daddr, key.af);
|
||||
|
||||
do {
|
||||
key.af = af;
|
||||
key.proto = proto;
|
||||
PF_ACPY(&key.addr[1], daddr, key.af);
|
||||
PF_ACPY(&key.addr[0], naddr, key.af);
|
||||
key.port[1] = dport;
|
||||
PF_ACPY(&key.addr[1], naddr, key.af);
|
||||
|
||||
/*
|
||||
* port search; start random, step;
|
||||
* similar 2 portloop in in_pcbbind
|
||||
*/
|
||||
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
|
||||
proto == IPPROTO_ICMP)) {
|
||||
key.port[0] = dport;
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
|
||||
return (0);
|
||||
} else if (low == 0 && high == 0) {
|
||||
key.port[0] = *nport;
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
|
||||
proto == IPPROTO_ICMP) || (low == 0 && high == 0)) {
|
||||
/*
|
||||
* XXX bug: icmp state don't use the id on both sides.
|
||||
* (traceroute -l through nat)
|
||||
*/
|
||||
key.port[1] = sport;
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
|
||||
*nport = sport;
|
||||
return (0);
|
||||
}
|
||||
} else if (low == high) {
|
||||
key.port[0] = htons(low);
|
||||
key.port[1] = htons(low);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
|
||||
*nport = htons(low);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
u_int16_t tmp;
|
||||
uint16_t tmp;
|
||||
|
||||
if (low > high) {
|
||||
tmp = low;
|
||||
@ -379,7 +383,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
|
||||
#endif
|
||||
/* low <= cut <= high */
|
||||
for (tmp = cut; tmp <= high; ++(tmp)) {
|
||||
key.port[0] = htons(tmp);
|
||||
key.port[1] = htons(tmp);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) ==
|
||||
#ifdef __FreeBSD__
|
||||
NULL) {
|
||||
@ -391,7 +395,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
|
||||
}
|
||||
}
|
||||
for (tmp = cut - 1; tmp >= low; --(tmp)) {
|
||||
key.port[0] = htons(tmp);
|
||||
key.port[1] = htons(tmp);
|
||||
if (pf_find_state_all(&key, PF_IN, NULL) ==
|
||||
#ifdef __FreeBSD__
|
||||
NULL) {
|
||||
@ -657,8 +661,8 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
|
||||
case PF_NORDR:
|
||||
return (NULL);
|
||||
case PF_NAT:
|
||||
if (pf_get_sport(pd->af, pd->proto, r, saddr,
|
||||
daddr, dport, naddr, nport, r->rpool.proxy_port[0],
|
||||
if (pf_get_sport(pd->af, pd->proto, r, saddr, sport, daddr,
|
||||
dport, naddr, nport, r->rpool.proxy_port[0],
|
||||
r->rpool.proxy_port[1], sn)) {
|
||||
DPFPRINTF(PF_DEBUG_MISC,
|
||||
("pf: NAT proxy port allocation "
|
||||
@ -786,6 +790,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
|
||||
pool_put(&pf_state_key_pl, *skp);
|
||||
#endif
|
||||
*skw = *sks = *nkp = *skp = NULL;
|
||||
*sn = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include <machine/rtems-bsd-kernel-space.h>
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006-2010 Broadcom Corporation
|
||||
* David Christensen <davidch@broadcom.com>. All rights reserved.
|
||||
* Copyright (c) 2006-2014 QLogic Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -13,9 +12,6 @@
|
||||
* 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 Broadcom Corporation nor the name of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written consent.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@ -108,13 +104,13 @@ static const struct bce_type bce_devs[] = {
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x1709,
|
||||
"HP NC371i Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5706 1000Base-T" },
|
||||
"QLogic NetXtreme II BCM5706 1000Base-T" },
|
||||
|
||||
/* BCM5706S controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102,
|
||||
"HP NC370F Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5706 1000Base-SX" },
|
||||
"QLogic NetXtreme II BCM5706 1000Base-SX" },
|
||||
|
||||
/* BCM5708C controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7037,
|
||||
@ -124,7 +120,7 @@ static const struct bce_type bce_devs[] = {
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7045,
|
||||
"HP NC374m PCIe Multifunction Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5708 1000Base-T" },
|
||||
"QLogic NetXtreme II BCM5708 1000Base-T" },
|
||||
|
||||
/* BCM5708S controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x1706,
|
||||
@ -134,7 +130,7 @@ static const struct bce_type bce_devs[] = {
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x703d,
|
||||
"HP NC373F PCIe Multifunc Giga Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5708 1000Base-SX" },
|
||||
"QLogic NetXtreme II BCM5708 1000Base-SX" },
|
||||
|
||||
/* BCM5709C controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7055,
|
||||
@ -142,7 +138,7 @@ static const struct bce_type bce_devs[] = {
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7059,
|
||||
"HP NC382T PCIe DP Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5709 1000Base-T" },
|
||||
"QLogic NetXtreme II BCM5709 1000Base-T" },
|
||||
|
||||
/* BCM5709S controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x171d,
|
||||
@ -150,11 +146,11 @@ static const struct bce_type bce_devs[] = {
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x7056,
|
||||
"HP NC382i DP Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5709 1000Base-SX" },
|
||||
"QLogic NetXtreme II BCM5709 1000Base-SX" },
|
||||
|
||||
/* BCM5716 controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5716, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5716 1000Base-T" },
|
||||
"QLogic NetXtreme II BCM5716 1000Base-T" },
|
||||
|
||||
{ 0, 0, 0, 0, NULL }
|
||||
};
|
||||
@ -5066,9 +5062,11 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
|
||||
|
||||
bce_reset_exit:
|
||||
/* Restore EMAC Mode bits needed to keep ASF/IPMI running. */
|
||||
val = REG_RD(sc, BCE_EMAC_MODE);
|
||||
val = (val & ~emac_mode_mask) | emac_mode_save;
|
||||
REG_WR(sc, BCE_EMAC_MODE, val);
|
||||
if (reset_code == BCE_DRV_MSG_CODE_RESET) {
|
||||
val = REG_RD(sc, BCE_EMAC_MODE);
|
||||
val = (val & ~emac_mode_mask) | emac_mode_save;
|
||||
REG_WR(sc, BCE_EMAC_MODE, val);
|
||||
}
|
||||
|
||||
DBEXIT(BCE_VERBOSE_RESET);
|
||||
return (rc);
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2006-2011 Broadcom Corporation
|
||||
* David Christensen <davidch@broadcom.com>. All rights reserved.
|
||||
* Copyright (c) 2006-2014 QLogic Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -10,9 +9,6 @@
|
||||
* 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 Broadcom Corporation nor the name of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written consent.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@ -31,7 +27,7 @@
|
||||
|
||||
/*
|
||||
* This file contains firmware data derived from proprietary unpublished
|
||||
* source code, Copyright (c) 2004-2011 Broadcom Corporation.
|
||||
* source code, Copyright (c) 2004-2014 QLogic Corporation.
|
||||
*
|
||||
* Permission is hereby granted for the distribution of this firmware data
|
||||
* in hexadecimal or equivalent format, provided this copyright notice also
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2006-2010 Broadcom Corporation
|
||||
* David Christensen <davidch@broadcom.com>. All rights reserved.
|
||||
* Copyright (c) 2006-2014 QLogic Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -10,9 +9,6 @@
|
||||
* 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 Broadcom Corporation nor the name of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written consent.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@ -6355,8 +6351,8 @@ struct fw_info {
|
||||
|
||||
#define BCE_TX_TIMEOUT 5
|
||||
|
||||
#define BCE_MAX_SEGMENTS 32
|
||||
#define BCE_TSO_MAX_SIZE 65536
|
||||
#define BCE_MAX_SEGMENTS 35
|
||||
#define BCE_TSO_MAX_SIZE (65535 + sizeof(struct ether_vlan_header))
|
||||
#define BCE_TSO_MAX_SEG_SIZE 4096
|
||||
|
||||
#define BCE_DMA_ALIGN 8
|
||||
|
@ -178,6 +178,8 @@ static const struct bge_type {
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5721 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5722 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5723 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5725 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5727 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5750 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5750M },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5751 },
|
||||
@ -197,6 +199,7 @@ static const struct bge_type {
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5761E },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5761S },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5761SE },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5762 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5764 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5780 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5780S },
|
||||
@ -219,11 +222,16 @@ static const struct bge_type {
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57760 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57761 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57762 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57764 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57765 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57766 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57767 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57780 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57781 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57782 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57785 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57786 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57787 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57788 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57790 },
|
||||
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57791 },
|
||||
@ -312,6 +320,7 @@ static const struct bge_revision {
|
||||
{ BGE_CHIPID_BCM5722_A0, "BCM5722 A0" },
|
||||
{ BGE_CHIPID_BCM5761_A0, "BCM5761 A0" },
|
||||
{ BGE_CHIPID_BCM5761_A1, "BCM5761 A1" },
|
||||
{ BGE_CHIPID_BCM5762_A0, "BCM5762 A0" },
|
||||
{ BGE_CHIPID_BCM5784_A0, "BCM5784 A0" },
|
||||
{ BGE_CHIPID_BCM5784_A1, "BCM5784 A1" },
|
||||
/* 5754 and 5787 share the same ASIC ID */
|
||||
@ -356,6 +365,7 @@ static const struct bge_revision bge_majorrevs[] = {
|
||||
{ BGE_ASICREV_BCM5717, "unknown BCM5717" },
|
||||
{ BGE_ASICREV_BCM5719, "unknown BCM5719" },
|
||||
{ BGE_ASICREV_BCM5720, "unknown BCM5720" },
|
||||
{ BGE_ASICREV_BCM5762, "unknown BCM5762" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
@ -1798,6 +1808,20 @@ bge_chipinit(struct bge_softc *sc)
|
||||
pci_write_config(sc->bge_dev, BGE_PCI_MSI_DATA + 2, val, 2);
|
||||
}
|
||||
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM57765 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM57766) {
|
||||
/*
|
||||
* For the 57766 and non Ax versions of 57765, bootcode
|
||||
* needs to setup the PCIE Fast Training Sequence (FTS)
|
||||
* value to prevent transmit hangs.
|
||||
*/
|
||||
if (sc->bge_chiprev != BGE_CHIPREV_57765_AX) {
|
||||
CSR_WRITE_4(sc, BGE_CPMU_PADRNG_CTL,
|
||||
CSR_READ_4(sc, BGE_CPMU_PADRNG_CTL) |
|
||||
BGE_CPMU_PADRNG_CTL_RDIV2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the PCI DMA control register.
|
||||
*/
|
||||
@ -1873,8 +1897,9 @@ bge_chipinit(struct bge_softc *sc)
|
||||
* a status tag update and leave interrupts permanently
|
||||
* disabled.
|
||||
*/
|
||||
if (sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
|
||||
sc->bge_asicrev != BGE_ASICREV_BCM57765)
|
||||
if (!BGE_IS_57765_PLUS(sc) &&
|
||||
sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
|
||||
sc->bge_asicrev != BGE_ASICREV_BCM5762)
|
||||
dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA;
|
||||
}
|
||||
pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4);
|
||||
@ -1883,7 +1908,8 @@ bge_chipinit(struct bge_softc *sc)
|
||||
* Set up general mode register.
|
||||
*/
|
||||
mode_ctl = bge_dma_swap_options(sc);
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762) {
|
||||
/* Retain Host-2-BMC settings written by APE firmware. */
|
||||
mode_ctl |= CSR_READ_4(sc, BGE_MODE_CTL) &
|
||||
(BGE_MODECTL_BYTESWAP_B2HRX_DATA |
|
||||
@ -1941,7 +1967,7 @@ bge_blockinit(struct bge_softc *sc)
|
||||
struct bge_rcb *rcb;
|
||||
bus_size_t vrcb;
|
||||
bge_hostaddr taddr;
|
||||
uint32_t dmactl, val;
|
||||
uint32_t dmactl, rdmareg, val;
|
||||
int i, limit;
|
||||
|
||||
/*
|
||||
@ -2212,6 +2238,11 @@ bge_blockinit(struct bge_softc *sc)
|
||||
if (!BGE_IS_5705_PLUS(sc))
|
||||
/* 5700 to 5704 had 16 send rings. */
|
||||
limit = BGE_TX_RINGS_EXTSSRAM_MAX;
|
||||
else if (BGE_IS_57765_PLUS(sc) ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762)
|
||||
limit = 2;
|
||||
else if (BGE_IS_5717_PLUS(sc))
|
||||
limit = 4;
|
||||
else
|
||||
limit = 1;
|
||||
vrcb = BGE_MEMWIN_START + BGE_SEND_RING_RCB;
|
||||
@ -2250,6 +2281,7 @@ bge_blockinit(struct bge_softc *sc)
|
||||
} else if (!BGE_IS_5705_PLUS(sc))
|
||||
limit = BGE_RX_RINGS_MAX;
|
||||
else if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762 ||
|
||||
BGE_IS_57765_PLUS(sc))
|
||||
limit = 4;
|
||||
else
|
||||
@ -2289,7 +2321,8 @@ bge_blockinit(struct bge_softc *sc)
|
||||
|
||||
/* Set inter-packet gap */
|
||||
val = 0x2620;
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720)
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762)
|
||||
val |= CSR_READ_4(sc, BGE_TX_LENGTHS) &
|
||||
(BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK);
|
||||
CSR_WRITE_4(sc, BGE_TX_LENGTHS, val);
|
||||
@ -2453,7 +2486,8 @@ bge_blockinit(struct bge_softc *sc)
|
||||
val |= BGE_RDMAMODE_TSO6_ENABLE;
|
||||
}
|
||||
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762) {
|
||||
val |= CSR_READ_4(sc, BGE_RDMA_MODE) &
|
||||
BGE_RDMAMODE_H2BNC_VLAN_DET;
|
||||
/*
|
||||
@ -2467,14 +2501,18 @@ bge_blockinit(struct bge_softc *sc)
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM57780 ||
|
||||
BGE_IS_5717_PLUS(sc)) {
|
||||
dmactl = CSR_READ_4(sc, BGE_RDMA_RSRVCTRL);
|
||||
BGE_IS_5717_PLUS(sc) || BGE_IS_57765_PLUS(sc)) {
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5762)
|
||||
rdmareg = BGE_RDMA_RSRVCTRL_REG2;
|
||||
else
|
||||
rdmareg = BGE_RDMA_RSRVCTRL;
|
||||
dmactl = CSR_READ_4(sc, rdmareg);
|
||||
/*
|
||||
* Adjust tx margin to prevent TX data corruption and
|
||||
* fix internal FIFO overflow.
|
||||
*/
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
|
||||
sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
|
||||
if (sc->bge_chipid == BGE_CHIPID_BCM5719_A0 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762) {
|
||||
dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK |
|
||||
BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK |
|
||||
BGE_RDMA_RSRVCTRL_TXMRGN_MASK);
|
||||
@ -2487,7 +2525,7 @@ bge_blockinit(struct bge_softc *sc)
|
||||
* The fix is to limit the number of RX BDs
|
||||
* the hardware would fetch at a fime.
|
||||
*/
|
||||
CSR_WRITE_4(sc, BGE_RDMA_RSRVCTRL, dmactl |
|
||||
CSR_WRITE_4(sc, rdmareg, dmactl |
|
||||
BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
|
||||
}
|
||||
|
||||
@ -2505,11 +2543,34 @@ bge_blockinit(struct bge_softc *sc)
|
||||
CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) |
|
||||
BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 |
|
||||
BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
|
||||
} else if (sc->bge_asicrev == BGE_ASICREV_BCM5762) {
|
||||
CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL_REG2,
|
||||
CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL_REG2) |
|
||||
BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K |
|
||||
BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
|
||||
}
|
||||
|
||||
CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
|
||||
DELAY(40);
|
||||
|
||||
if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
|
||||
for (i = 0; i < BGE_NUM_RDMA_CHANNELS / 2; i++) {
|
||||
val = CSR_READ_4(sc, BGE_RDMA_LENGTH + i * 4);
|
||||
if ((val & 0xFFFF) > BGE_FRAMELEN)
|
||||
break;
|
||||
if (((val >> 16) & 0xFFFF) > BGE_FRAMELEN)
|
||||
break;
|
||||
}
|
||||
if (i != BGE_NUM_RDMA_CHANNELS / 2) {
|
||||
val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
|
||||
val |= BGE_RDMA_TX_LENGTH_WA_5719;
|
||||
else
|
||||
val |= BGE_RDMA_TX_LENGTH_WA_5720;
|
||||
CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on RX data completion state machine */
|
||||
CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
|
||||
|
||||
@ -2636,6 +2697,12 @@ bge_chipid(device_t dev)
|
||||
case BCOM_DEVICEID_BCM5718:
|
||||
case BCOM_DEVICEID_BCM5719:
|
||||
case BCOM_DEVICEID_BCM5720:
|
||||
case BCOM_DEVICEID_BCM5725:
|
||||
case BCOM_DEVICEID_BCM5727:
|
||||
case BCOM_DEVICEID_BCM5762:
|
||||
case BCOM_DEVICEID_BCM57764:
|
||||
case BCOM_DEVICEID_BCM57767:
|
||||
case BCOM_DEVICEID_BCM57787:
|
||||
id = pci_read_config(dev,
|
||||
BGE_PCI_GEN2_PRODID_ASICREV, 4);
|
||||
break;
|
||||
@ -2644,7 +2711,9 @@ bge_chipid(device_t dev)
|
||||
case BCOM_DEVICEID_BCM57765:
|
||||
case BCOM_DEVICEID_BCM57766:
|
||||
case BCOM_DEVICEID_BCM57781:
|
||||
case BCOM_DEVICEID_BCM57782:
|
||||
case BCOM_DEVICEID_BCM57785:
|
||||
case BCOM_DEVICEID_BCM57786:
|
||||
case BCOM_DEVICEID_BCM57791:
|
||||
case BCOM_DEVICEID_BCM57795:
|
||||
id = pci_read_config(dev,
|
||||
@ -3259,7 +3328,7 @@ bge_attach(device_t dev)
|
||||
struct bge_softc *sc;
|
||||
uint32_t hwcfg = 0, misccfg, pcistate;
|
||||
u_char eaddr[ETHER_ADDR_LEN];
|
||||
int capmask, error, msicount, reg, rid, trys;
|
||||
int capmask, error, reg, rid, trys;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->bge_dev = dev;
|
||||
@ -3268,11 +3337,11 @@ bge_attach(device_t dev)
|
||||
TASK_INIT(&sc->bge_intr_task, 0, bge_intr_task, sc);
|
||||
callout_init_mtx(&sc->bge_stat_ch, &sc->bge_mtx, 0);
|
||||
|
||||
/*
|
||||
* Map control/status registers.
|
||||
*/
|
||||
pci_enable_busmaster(dev);
|
||||
|
||||
/*
|
||||
* Allocate control/status registers.
|
||||
*/
|
||||
rid = PCIR_BAR(0);
|
||||
sc->bge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
@ -3336,6 +3405,7 @@ bge_attach(device_t dev)
|
||||
|
||||
/* Save chipset family. */
|
||||
switch (sc->bge_asicrev) {
|
||||
case BGE_ASICREV_BCM5762:
|
||||
case BGE_ASICREV_BCM57765:
|
||||
case BGE_ASICREV_BCM57766:
|
||||
sc->bge_flags |= BGE_FLAG_57765_PLUS;
|
||||
@ -3346,10 +3416,18 @@ bge_attach(device_t dev)
|
||||
sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS |
|
||||
BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO |
|
||||
BGE_FLAG_JUMBO_FRAME;
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
|
||||
sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
|
||||
/* Jumbo frame on BCM5719 A0 does not work. */
|
||||
sc->bge_flags &= ~BGE_FLAG_JUMBO;
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5720) {
|
||||
/*
|
||||
* Enable work around for DMA engine miscalculation
|
||||
* of TXMBUF available space.
|
||||
*/
|
||||
sc->bge_flags |= BGE_FLAG_RDMA_BUG;
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
|
||||
sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
|
||||
/* Jumbo frame on BCM5719 A0 does not work. */
|
||||
sc->bge_flags &= ~BGE_FLAG_JUMBO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BGE_ASICREV_BCM5755:
|
||||
@ -3388,6 +3466,7 @@ bge_attach(device_t dev)
|
||||
case BGE_ASICREV_BCM5719:
|
||||
case BGE_ASICREV_BCM5720:
|
||||
case BGE_ASICREV_BCM5761:
|
||||
case BGE_ASICREV_BCM5762:
|
||||
sc->bge_flags |= BGE_FLAG_APE;
|
||||
break;
|
||||
}
|
||||
@ -3572,13 +3651,8 @@ bge_attach(device_t dev)
|
||||
rid = 0;
|
||||
if (pci_find_cap(sc->bge_dev, PCIY_MSI, ®) == 0) {
|
||||
sc->bge_msicap = reg;
|
||||
if (bge_can_use_msi(sc)) {
|
||||
msicount = pci_msi_count(dev);
|
||||
if (msicount > 1)
|
||||
msicount = 1;
|
||||
} else
|
||||
msicount = 0;
|
||||
if (msicount == 1 && pci_alloc_msi(dev, &msicount) == 0) {
|
||||
reg = 1;
|
||||
if (bge_can_use_msi(sc) && pci_alloc_msi(dev, ®) == 0) {
|
||||
rid = 1;
|
||||
sc->bge_flags |= BGE_FLAG_MSI;
|
||||
}
|
||||
@ -3595,7 +3669,7 @@ bge_attach(device_t dev)
|
||||
#endif
|
||||
|
||||
sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
RF_ACTIVE | (rid != 0 ? 0 : RF_SHAREABLE));
|
||||
|
||||
if (sc->bge_irq == NULL) {
|
||||
device_printf(sc->bge_dev, "couldn't map interrupt\n");
|
||||
@ -3938,20 +4012,19 @@ bge_release_resources(struct bge_softc *sc)
|
||||
if (sc->bge_intrhand != NULL)
|
||||
bus_teardown_intr(dev, sc->bge_irq, sc->bge_intrhand);
|
||||
|
||||
if (sc->bge_irq != NULL)
|
||||
if (sc->bge_irq != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->bge_flags & BGE_FLAG_MSI ? 1 : 0, sc->bge_irq);
|
||||
|
||||
if (sc->bge_flags & BGE_FLAG_MSI)
|
||||
rman_get_rid(sc->bge_irq), sc->bge_irq);
|
||||
pci_release_msi(dev);
|
||||
}
|
||||
|
||||
if (sc->bge_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
PCIR_BAR(0), sc->bge_res);
|
||||
rman_get_rid(sc->bge_res), sc->bge_res);
|
||||
|
||||
if (sc->bge_res2 != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
PCIR_BAR(2), sc->bge_res2);
|
||||
rman_get_rid(sc->bge_res2), sc->bge_res2);
|
||||
|
||||
if (sc->bge_ifp != NULL)
|
||||
if_free(sc->bge_ifp);
|
||||
@ -4767,6 +4840,7 @@ bge_stats_update_regs(struct bge_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct bge_mac_stats *stats;
|
||||
uint32_t val;
|
||||
|
||||
ifp = sc->bge_ifp;
|
||||
stats = &sc->bge_mac_stats;
|
||||
@ -4867,6 +4941,24 @@ bge_stats_update_regs(struct bge_softc *sc)
|
||||
ifp->if_collisions = (u_long)stats->etherStatsCollisions;
|
||||
ifp->if_ierrors = (u_long)(stats->NoMoreRxBDs + stats->InputDiscards +
|
||||
stats->InputErrors);
|
||||
|
||||
if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
|
||||
/*
|
||||
* If controller transmitted more than BGE_NUM_RDMA_CHANNELS
|
||||
* frames, it's safe to disable workaround for DMA engine's
|
||||
* miscalculation of TXMBUF space.
|
||||
*/
|
||||
if (stats->ifHCOutUcastPkts + stats->ifHCOutMulticastPkts +
|
||||
stats->ifHCOutBroadcastPkts > BGE_NUM_RDMA_CHANNELS) {
|
||||
val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
|
||||
val &= ~BGE_RDMA_TX_LENGTH_WA_5719;
|
||||
else
|
||||
val &= ~BGE_RDMA_TX_LENGTH_WA_5720;
|
||||
CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
|
||||
sc->bge_flags &= ~BGE_FLAG_RDMA_BUG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5196,17 +5288,51 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx)
|
||||
csum_flags |= BGE_TXBDFLAG_VLAN_TAG;
|
||||
vlan_tag = m->m_pkthdr.ether_vtag;
|
||||
}
|
||||
for (i = 0; ; i++) {
|
||||
d = &sc->bge_ldata.bge_tx_ring[idx];
|
||||
d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
|
||||
d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
|
||||
d->bge_len = segs[i].ds_len;
|
||||
d->bge_flags = csum_flags;
|
||||
d->bge_vlan_tag = vlan_tag;
|
||||
d->bge_mss = mss;
|
||||
if (i == nsegs - 1)
|
||||
break;
|
||||
BGE_INC(idx, BGE_TX_RING_CNT);
|
||||
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5762 &&
|
||||
(m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
/*
|
||||
* 5725 family of devices corrupts TSO packets when TSO DMA
|
||||
* buffers cross into regions which are within MSS bytes of
|
||||
* a 4GB boundary. If we encounter the condition, drop the
|
||||
* packet.
|
||||
*/
|
||||
for (i = 0; ; i++) {
|
||||
d = &sc->bge_ldata.bge_tx_ring[idx];
|
||||
d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
|
||||
d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
|
||||
d->bge_len = segs[i].ds_len;
|
||||
if (d->bge_addr.bge_addr_lo + segs[i].ds_len + mss <
|
||||
d->bge_addr.bge_addr_lo)
|
||||
break;
|
||||
d->bge_flags = csum_flags;
|
||||
d->bge_vlan_tag = vlan_tag;
|
||||
d->bge_mss = mss;
|
||||
if (i == nsegs - 1)
|
||||
break;
|
||||
BGE_INC(idx, BGE_TX_RING_CNT);
|
||||
}
|
||||
if (i != nsegs - 1) {
|
||||
bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag, map,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(sc->bge_cdata.bge_tx_mtag, map);
|
||||
m_freem(*m_head);
|
||||
*m_head = NULL;
|
||||
return (EIO);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; ; i++) {
|
||||
d = &sc->bge_ldata.bge_tx_ring[idx];
|
||||
d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
|
||||
d->bge_addr.bge_addr_hi = BGE_ADDR_HI(segs[i].ds_addr);
|
||||
d->bge_len = segs[i].ds_len;
|
||||
d->bge_flags = csum_flags;
|
||||
d->bge_vlan_tag = vlan_tag;
|
||||
d->bge_mss = mss;
|
||||
if (i == nsegs - 1)
|
||||
break;
|
||||
BGE_INC(idx, BGE_TX_RING_CNT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark the last segment as end of packet... */
|
||||
@ -5433,7 +5559,8 @@ bge_init_locked(struct bge_softc *sc)
|
||||
mode = CSR_READ_4(sc, BGE_TX_MODE);
|
||||
if (BGE_IS_5755_PLUS(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5906)
|
||||
mode |= BGE_TXMODE_MBUF_LOCKUP_FIX;
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5720 ||
|
||||
sc->bge_asicrev == BGE_ASICREV_BCM5762) {
|
||||
mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
|
||||
mode |= CSR_READ_4(sc, BGE_TX_MODE) &
|
||||
(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
|
||||
|
@ -331,6 +331,7 @@
|
||||
#define BGE_CHIPID_BCM5717_B0 0x05717100
|
||||
#define BGE_CHIPID_BCM5719_A0 0x05719000
|
||||
#define BGE_CHIPID_BCM5720_A0 0x05720000
|
||||
#define BGE_CHIPID_BCM5762_A0 0x05762000
|
||||
#define BGE_CHIPID_BCM57765_A0 0x57785000
|
||||
#define BGE_CHIPID_BCM57765_B0 0x57785100
|
||||
|
||||
@ -357,6 +358,7 @@
|
||||
#define BGE_ASICREV_BCM5719 0x5719
|
||||
#define BGE_ASICREV_BCM5720 0x5720
|
||||
#define BGE_ASICREV_BCM5761 0x5761
|
||||
#define BGE_ASICREV_BCM5762 0x5762
|
||||
#define BGE_ASICREV_BCM5784 0x5784
|
||||
#define BGE_ASICREV_BCM5785 0x5785
|
||||
#define BGE_ASICREV_BCM57765 0x57785
|
||||
@ -378,6 +380,7 @@
|
||||
#define BGE_CHIPREV_5717_AX 0x57170
|
||||
#define BGE_CHIPREV_5717_BX 0x57171
|
||||
#define BGE_CHIPREV_5761_AX 0x57611
|
||||
#define BGE_CHIPREV_57765_AX 0x577850
|
||||
#define BGE_CHIPREV_5784_AX 0x57841
|
||||
|
||||
/* PCI DMA Read/Write Control register */
|
||||
@ -1289,6 +1292,7 @@
|
||||
#define BGE_CPMU_MUTEX_REQ 0x365C
|
||||
#define BGE_CPMU_MUTEX_GNT 0x3660
|
||||
#define BGE_CPMU_PHY_STRAP 0x3664
|
||||
#define BGE_CPMU_PADRNG_CTL 0x3668
|
||||
|
||||
/* Central Power Management Unit (CPMU) register */
|
||||
#define BGE_CPMU_CTRL_LINK_IDLE_MODE 0x00000200
|
||||
@ -1328,6 +1332,9 @@
|
||||
/* CPMU GPHY Strap register */
|
||||
#define BGE_CPMU_PHY_STRAP_IS_SERDES 0x00000020
|
||||
|
||||
/* CPMU Padring Control register */
|
||||
#define BGE_CPMU_PADRNG_CTL_RDIV2 0x00040000
|
||||
|
||||
/*
|
||||
* Mbuf Cluster Free registers (has nothing to do with BSD mbufs)
|
||||
*/
|
||||
@ -1539,6 +1546,8 @@
|
||||
*/
|
||||
#define BGE_RDMA_MODE 0x4800
|
||||
#define BGE_RDMA_STATUS 0x4804
|
||||
#define BGE_RDMA_RSRVCTRL_REG2 0x4890
|
||||
#define BGE_RDMA_LSO_CRPTEN_CTRL_REG2 0x48A0
|
||||
#define BGE_RDMA_RSRVCTRL 0x4900
|
||||
#define BGE_RDMA_LSO_CRPTEN_CTRL 0x4910
|
||||
|
||||
@ -1586,6 +1595,8 @@
|
||||
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 0x00020000
|
||||
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
|
||||
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K 0x000C0000
|
||||
#define BGE_RDMA_TX_LENGTH_WA_5719 0x02000000
|
||||
#define BGE_RDMA_TX_LENGTH_WA_5720 0x00200000
|
||||
|
||||
/* BD Read DMA Mode register */
|
||||
#define BGE_RDMA_BD_MODE 0x4A00
|
||||
@ -1603,6 +1614,9 @@
|
||||
#define BGE_RDMA_NON_LSO_MODE_RESET 0x00000001
|
||||
#define BGE_RDMA_NON_LSO_MODE_ENABLE 0x00000002
|
||||
|
||||
#define BGE_RDMA_LENGTH 0x4BE0
|
||||
#define BGE_NUM_RDMA_CHANNELS 4
|
||||
|
||||
/*
|
||||
* Write DMA control registers
|
||||
*/
|
||||
@ -2444,6 +2458,8 @@ struct bge_status_block {
|
||||
#define BCOM_DEVICEID_BCM5721 0x1659
|
||||
#define BCOM_DEVICEID_BCM5722 0x165A
|
||||
#define BCOM_DEVICEID_BCM5723 0x165B
|
||||
#define BCOM_DEVICEID_BCM5725 0x1643
|
||||
#define BCOM_DEVICEID_BCM5727 0x16F3
|
||||
#define BCOM_DEVICEID_BCM5750 0x1676
|
||||
#define BCOM_DEVICEID_BCM5750M 0x167C
|
||||
#define BCOM_DEVICEID_BCM5751 0x1677
|
||||
@ -2463,6 +2479,7 @@ struct bge_status_block {
|
||||
#define BCOM_DEVICEID_BCM5761E 0x1680
|
||||
#define BCOM_DEVICEID_BCM5761S 0x1688
|
||||
#define BCOM_DEVICEID_BCM5761SE 0x1689
|
||||
#define BCOM_DEVICEID_BCM5762 0x1687
|
||||
#define BCOM_DEVICEID_BCM5764 0x1684
|
||||
#define BCOM_DEVICEID_BCM5780 0x166A
|
||||
#define BCOM_DEVICEID_BCM5780S 0x166B
|
||||
@ -2485,11 +2502,16 @@ struct bge_status_block {
|
||||
#define BCOM_DEVICEID_BCM57760 0x1690
|
||||
#define BCOM_DEVICEID_BCM57761 0x16B0
|
||||
#define BCOM_DEVICEID_BCM57762 0x1682
|
||||
#define BCOM_DEVICEID_BCM57764 0x1642
|
||||
#define BCOM_DEVICEID_BCM57765 0x16B4
|
||||
#define BCOM_DEVICEID_BCM57766 0x1686
|
||||
#define BCOM_DEVICEID_BCM57767 0x1683
|
||||
#define BCOM_DEVICEID_BCM57780 0x1692
|
||||
#define BCOM_DEVICEID_BCM57781 0x16B1
|
||||
#define BCOM_DEVICEID_BCM57782 0x16B7
|
||||
#define BCOM_DEVICEID_BCM57785 0x16B5
|
||||
#define BCOM_DEVICEID_BCM57786 0x16B3
|
||||
#define BCOM_DEVICEID_BCM57787 0x1641
|
||||
#define BCOM_DEVICEID_BCM57788 0x1691
|
||||
#define BCOM_DEVICEID_BCM57790 0x1694
|
||||
#define BCOM_DEVICEID_BCM57791 0x16B2
|
||||
@ -2829,7 +2851,7 @@ struct bge_gib {
|
||||
*/
|
||||
|
||||
#define BGE_NSEG_JUMBO 4
|
||||
#define BGE_NSEG_NEW 32
|
||||
#define BGE_NSEG_NEW 35
|
||||
#define BGE_TSOSEG_SZ 4096
|
||||
|
||||
/* Maximum DMA address for controllers that have 40bit DMA address bug. */
|
||||
@ -2982,6 +3004,7 @@ struct bge_softc {
|
||||
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
|
||||
#define BGE_FLAG_4K_RDMA_BUG 0x10000000
|
||||
#define BGE_FLAG_MBOX_REORDER 0x20000000
|
||||
#define BGE_FLAG_RDMA_BUG 0x40000000
|
||||
uint32_t bge_mfw_flags; /* Management F/W flags */
|
||||
#define BGE_MFW_ON_RXCPU 0x00000001
|
||||
#define BGE_MFW_ON_APE 0x00000002
|
||||
|
@ -129,7 +129,7 @@
|
||||
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
|
||||
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
|
||||
|
||||
#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */
|
||||
#define E1000_RXDEXT_STATERR_TST 0x00010000 /* Time Stamp taken */
|
||||
#define E1000_RXDEXT_STATERR_LB 0x00040000
|
||||
#define E1000_RXDEXT_STATERR_CE 0x01000000
|
||||
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
||||
|
@ -3837,8 +3837,7 @@ em_txeof(struct tx_ring *txr)
|
||||
|
||||
EM_TX_LOCK_ASSERT(txr);
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_tx_irq(ifp, txr->me |
|
||||
(NETMAP_LOCKED_ENTER | NETMAP_LOCKED_EXIT)))
|
||||
if (netmap_tx_irq(ifp, txr->me))
|
||||
return;
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
@ -4355,7 +4354,7 @@ em_initialize_receive_unit(struct adapter *adapter)
|
||||
* preserve the rx buffers passed to userspace.
|
||||
*/
|
||||
if (ifp->if_capenable & IFCAP_NETMAP)
|
||||
rdt -= NA(adapter->ifp)->rx_rings[i].nr_hwavail;
|
||||
rdt -= nm_kr_rxspace(&NA(adapter->ifp)->rx_rings[i]);
|
||||
#endif /* DEV_NETMAP */
|
||||
E1000_WRITE_REG(hw, E1000_RDT(i), rdt);
|
||||
}
|
||||
@ -4434,8 +4433,10 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
|
||||
EM_RX_LOCK(rxr);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed))
|
||||
if (netmap_rx_irq(ifp, rxr->me, &processed)) {
|
||||
EM_RX_UNLOCK(rxr);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = rxr->next_to_check, processed = 0; count != 0;) {
|
||||
|
@ -2885,6 +2885,9 @@ igb_setup_msix(struct adapter *adapter)
|
||||
if (queues > maxqueues)
|
||||
queues = maxqueues;
|
||||
|
||||
/* reflect correct sysctl value */
|
||||
igb_num_queues = queues;
|
||||
|
||||
/*
|
||||
** One vector (RX/TX pair) per queue
|
||||
** plus an additional for Link interrupt
|
||||
@ -3909,8 +3912,7 @@ igb_txeof(struct tx_ring *txr)
|
||||
IGB_TX_LOCK_ASSERT(txr);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_tx_irq(ifp, txr->me |
|
||||
(NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT)))
|
||||
if (netmap_tx_irq(ifp, txr->me ))
|
||||
return (FALSE);
|
||||
#endif /* DEV_NETMAP */
|
||||
if (txr->tx_avail == adapter->num_tx_desc) {
|
||||
@ -4571,13 +4573,13 @@ igb_initialize_receive_units(struct adapter *adapter)
|
||||
* an init() while a netmap client is active must
|
||||
* preserve the rx buffers passed to userspace.
|
||||
* In this driver it means we adjust RDT to
|
||||
* somthing different from next_to_refresh
|
||||
* something different from next_to_refresh
|
||||
* (which is not used in netmap mode).
|
||||
*/
|
||||
if (ifp->if_capenable & IFCAP_NETMAP) {
|
||||
struct netmap_adapter *na = NA(adapter->ifp);
|
||||
struct netmap_kring *kring = &na->rx_rings[i];
|
||||
int t = rxr->next_to_refresh - kring->nr_hwavail;
|
||||
int t = rxr->next_to_refresh - nm_kr_rxspace(kring);
|
||||
|
||||
if (t >= adapter->num_rx_desc)
|
||||
t -= adapter->num_rx_desc;
|
||||
@ -4765,8 +4767,10 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
|
||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed))
|
||||
if (netmap_rx_irq(ifp, rxr->me, &processed)) {
|
||||
IGB_RX_UNLOCK(rxr);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
/* Main clean loop */
|
||||
|
@ -2680,7 +2680,7 @@ lem_setup_transmit_structures(struct adapter *adapter)
|
||||
void *addr;
|
||||
|
||||
addr = PNMB(slot + si, &paddr);
|
||||
adapter->tx_desc_base[si].buffer_addr = htole64(paddr);
|
||||
adapter->tx_desc_base[i].buffer_addr = htole64(paddr);
|
||||
/* reload the map for netmap mode */
|
||||
netmap_load_map(adapter->txtag, tx_buffer->map, addr);
|
||||
}
|
||||
@ -2987,7 +2987,7 @@ lem_txeof(struct adapter *adapter)
|
||||
EM_TX_LOCK_ASSERT(adapter);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT)))
|
||||
if (netmap_tx_irq(ifp, 0))
|
||||
return;
|
||||
#endif /* DEV_NETMAP */
|
||||
if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
|
||||
@ -3370,7 +3370,7 @@ lem_initialize_receive_unit(struct adapter *adapter)
|
||||
#ifdef DEV_NETMAP
|
||||
/* preserve buffers already made available to clients */
|
||||
if (ifp->if_capenable & IFCAP_NETMAP)
|
||||
rctl -= NA(adapter->ifp)->rx_rings[0].nr_hwavail;
|
||||
rctl -= nm_kr_rxspace(&NA(adapter->ifp)->rx_rings[0]);
|
||||
#endif /* DEV_NETMAP */
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl);
|
||||
|
||||
@ -3456,8 +3456,10 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_rx_irq(ifp, 0 | NETMAP_LOCKED_ENTER, &rx_sent))
|
||||
if (netmap_rx_irq(ifp, 0, &rx_sent)) {
|
||||
EM_RX_UNLOCK(adapter);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
|
||||
|
@ -250,7 +250,7 @@ struct fxp_cb_ucode {
|
||||
/*
|
||||
* Number of DMA segments in a TxCB.
|
||||
*/
|
||||
#define FXP_NTXSEG 32
|
||||
#define FXP_NTXSEG 35
|
||||
|
||||
struct fxp_tbd {
|
||||
uint32_t tb_addr;
|
||||
|
@ -149,6 +149,7 @@ static const struct mii_phydesc brgphys[] = {
|
||||
MII_PHY_DESC(BROADCOM3, BCM5720C),
|
||||
MII_PHY_DESC(BROADCOM3, BCM57765),
|
||||
MII_PHY_DESC(BROADCOM3, BCM57780),
|
||||
MII_PHY_DESC(BROADCOM4, BCM5725C),
|
||||
MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906),
|
||||
MII_PHY_END
|
||||
};
|
||||
@ -934,6 +935,8 @@ brgphy_reset(struct mii_softc *sc)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MII_OUI_BROADCOM4:
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = sc->mii_pdata->mii_ifp;
|
||||
|
@ -164,7 +164,7 @@ static device_method_t pci_methods[] = {
|
||||
DEVMETHOD(bus_delete_resource, pci_delete_resource),
|
||||
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
|
||||
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_release_resource, pci_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, pci_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
|
||||
@ -347,6 +347,11 @@ SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN,
|
||||
Disable this if you depend on BIOS emulation of USB devices, that is\n\
|
||||
you use USB devices (like keyboard or mouse) but do not load USB drivers");
|
||||
|
||||
static int pci_clear_bars;
|
||||
TUNABLE_INT("hw.pci.clear_bars", &pci_clear_bars);
|
||||
SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0,
|
||||
"Ignore firmware-assigned resources for BARs.");
|
||||
|
||||
static int
|
||||
pci_has_quirk(uint32_t devid, int quirk)
|
||||
{
|
||||
@ -999,7 +1004,7 @@ pci_read_vpd(device_t pcib, pcicfgregs *cfg)
|
||||
state = -2;
|
||||
break;
|
||||
}
|
||||
dflen = byte2;
|
||||
cfg->vpd.vpd_ros[off].len = dflen = byte2;
|
||||
if (dflen == 0 &&
|
||||
strncmp(cfg->vpd.vpd_ros[off].keyword, "RV",
|
||||
2) == 0) {
|
||||
@ -1200,6 +1205,17 @@ pci_get_vpd_readonly_method(device_t dev, device_t child, const char *kw,
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
struct pcicfg_vpd *
|
||||
pci_fetch_vpd_list(device_t dev)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(dev);
|
||||
pcicfgregs *cfg = &dinfo->cfg;
|
||||
|
||||
if (!cfg->vpd.vpd_cached && cfg->vpd.vpd_reg != 0)
|
||||
pci_read_vpd(device_get_parent(device_get_parent(dev)), cfg);
|
||||
return (&cfg->vpd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the requested extended capability and return the offset in
|
||||
* configuration space via the pointer provided. The function returns
|
||||
@ -2668,7 +2684,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
|
||||
struct pci_map *pm;
|
||||
pci_addr_t base, map, testval;
|
||||
pci_addr_t start, end, count;
|
||||
int barlen, basezero, maprange, mapsize, type;
|
||||
int barlen, basezero, flags, maprange, mapsize, type;
|
||||
uint16_t cmd;
|
||||
struct resource *res;
|
||||
|
||||
@ -2774,7 +2790,10 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
|
||||
}
|
||||
|
||||
count = (pci_addr_t)1 << mapsize;
|
||||
if (basezero || base == pci_mapbase(testval)) {
|
||||
flags = RF_ALIGNMENT_LOG2(mapsize);
|
||||
if (prefetch)
|
||||
flags |= RF_PREFETCHABLE;
|
||||
if (basezero || base == pci_mapbase(testval) || pci_clear_bars) {
|
||||
start = 0; /* Let the parent decide. */
|
||||
end = ~0ul;
|
||||
} else {
|
||||
@ -2790,7 +2809,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
|
||||
* pci_alloc_resource().
|
||||
*/
|
||||
res = resource_list_reserve(rl, bus, dev, type, ®, start, end, count,
|
||||
prefetch ? RF_PREFETCHABLE : 0);
|
||||
flags);
|
||||
if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) {
|
||||
/*
|
||||
* If the allocation fails, try to allocate a resource for
|
||||
@ -2801,7 +2820,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
|
||||
resource_list_delete(rl, type, reg);
|
||||
resource_list_add(rl, type, reg, 0, ~0ul, count);
|
||||
res = resource_list_reserve(rl, bus, dev, type, ®, 0, ~0ul,
|
||||
count, prefetch ? RF_PREFETCHABLE : 0);
|
||||
count, flags);
|
||||
}
|
||||
if (res == NULL) {
|
||||
/*
|
||||
@ -3650,105 +3669,107 @@ static const struct
|
||||
{
|
||||
int class;
|
||||
int subclass;
|
||||
int report; /* 0 = bootverbose, 1 = always */
|
||||
const char *desc;
|
||||
} pci_nomatch_tab[] = {
|
||||
{PCIC_OLD, -1, "old"},
|
||||
{PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"},
|
||||
{PCIC_OLD, PCIS_OLD_VGA, "VGA-compatible display device"},
|
||||
{PCIC_STORAGE, -1, "mass storage"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SCSI, "SCSI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IDE, "ATA"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_FLOPPY, "floppy disk"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IPI, "IPI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_RAID, "RAID"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_ATA_ADMA, "ATA (ADMA)"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SATA, "SATA"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SAS, "SAS"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_NVM, "NVM"},
|
||||
{PCIC_NETWORK, -1, "network"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ETHERNET, "ethernet"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_TOKENRING, "token ring"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_FDDI, "fddi"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ATM, "ATM"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ISDN, "ISDN"},
|
||||
{PCIC_DISPLAY, -1, "display"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_VGA, "VGA"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_XGA, "XGA"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_3D, "3D"},
|
||||
{PCIC_MULTIMEDIA, -1, "multimedia"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_VIDEO, "video"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_AUDIO, "audio"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_TELE, "telephony"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_HDA, "HDA"},
|
||||
{PCIC_MEMORY, -1, "memory"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_RAM, "RAM"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_FLASH, "flash"},
|
||||
{PCIC_BRIDGE, -1, "bridge"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_HOST, "HOST-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_ISA, "PCI-ISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_EISA, "PCI-EISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_MCA, "PCI-MCA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCI, "PCI-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCMCIA, "PCI-PCMCIA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_NUBUS, "PCI-NuBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_CARDBUS, "PCI-CardBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_RACEWAY, "PCI-RACEway"},
|
||||
{PCIC_SIMPLECOMM, -1, "simple comms"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_UART, "UART"}, /* could detect 16550 */
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_PAR, "parallel port"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_MULSER, "multiport serial"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_MODEM, "generic modem"},
|
||||
{PCIC_BASEPERIPH, -1, "base peripheral"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PIC, "interrupt controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_DMA, "DMA controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_TIMER, "timer"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, "realtime clock"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PCIHOT, "PCI hot-plug controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_SDHC, "SD host controller"},
|
||||
{PCIC_INPUTDEV, -1, "input device"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, "keyboard"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,"digitizer"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_MOUSE, "mouse"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_SCANNER, "scanner"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_GAMEPORT, "gameport"},
|
||||
{PCIC_DOCKING, -1, "docking station"},
|
||||
{PCIC_PROCESSOR, -1, "processor"},
|
||||
{PCIC_SERIALBUS, -1, "serial bus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FW, "FireWire"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_ACCESS, "AccessBus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SSA, "SSA"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_USB, "USB"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FC, "Fibre Channel"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SMBUS, "SMBus"},
|
||||
{PCIC_WIRELESS, -1, "wireless controller"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_IRDA, "iRDA"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_IR, "IR"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_RF, "RF"},
|
||||
{PCIC_INTELLIIO, -1, "intelligent I/O controller"},
|
||||
{PCIC_INTELLIIO, PCIS_INTELLIIO_I2O, "I2O"},
|
||||
{PCIC_SATCOM, -1, "satellite communication"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_TV, "sat TV"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_AUDIO, "sat audio"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_VOICE, "sat voice"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_DATA, "sat data"},
|
||||
{PCIC_CRYPTO, -1, "encrypt/decrypt"},
|
||||
{PCIC_CRYPTO, PCIS_CRYPTO_NETCOMP, "network/computer crypto"},
|
||||
{PCIC_CRYPTO, PCIS_CRYPTO_ENTERTAIN, "entertainment crypto"},
|
||||
{PCIC_DASP, -1, "dasp"},
|
||||
{PCIC_DASP, PCIS_DASP_DPIO, "DPIO module"},
|
||||
{0, 0, NULL}
|
||||
{PCIC_OLD, -1, 1, "old"},
|
||||
{PCIC_OLD, PCIS_OLD_NONVGA, 1, "non-VGA display device"},
|
||||
{PCIC_OLD, PCIS_OLD_VGA, 1, "VGA-compatible display device"},
|
||||
{PCIC_STORAGE, -1, 1, "mass storage"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SCSI, 1, "SCSI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IDE, 1, "ATA"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_FLOPPY, 1, "floppy disk"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_IPI, 1, "IPI"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_RAID, 1, "RAID"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_ATA_ADMA, 1, "ATA (ADMA)"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SATA, 1, "SATA"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_SAS, 1, "SAS"},
|
||||
{PCIC_STORAGE, PCIS_STORAGE_NVM, 1, "NVM"},
|
||||
{PCIC_NETWORK, -1, 1, "network"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ETHERNET, 1, "ethernet"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_TOKENRING, 1, "token ring"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_FDDI, 1, "fddi"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ATM, 1, "ATM"},
|
||||
{PCIC_NETWORK, PCIS_NETWORK_ISDN, 1, "ISDN"},
|
||||
{PCIC_DISPLAY, -1, 1, "display"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_VGA, 1, "VGA"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_XGA, 1, "XGA"},
|
||||
{PCIC_DISPLAY, PCIS_DISPLAY_3D, 1, "3D"},
|
||||
{PCIC_MULTIMEDIA, -1, 1, "multimedia"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_VIDEO, 1, "video"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_AUDIO, 1, "audio"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_TELE, 1, "telephony"},
|
||||
{PCIC_MULTIMEDIA, PCIS_MULTIMEDIA_HDA, 1, "HDA"},
|
||||
{PCIC_MEMORY, -1, 1, "memory"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_RAM, 1, "RAM"},
|
||||
{PCIC_MEMORY, PCIS_MEMORY_FLASH, 1, "flash"},
|
||||
{PCIC_BRIDGE, -1, 1, "bridge"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_HOST, 1, "HOST-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_ISA, 1, "PCI-ISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_EISA, 1, "PCI-EISA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_MCA, 1, "PCI-MCA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCI, 1, "PCI-PCI"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_PCMCIA, 1, "PCI-PCMCIA"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_NUBUS, 1, "PCI-NuBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_CARDBUS, 1, "PCI-CardBus"},
|
||||
{PCIC_BRIDGE, PCIS_BRIDGE_RACEWAY, 1, "PCI-RACEway"},
|
||||
{PCIC_SIMPLECOMM, -1, 1, "simple comms"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_UART, 1, "UART"}, /* could detect 16550 */
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_PAR, 1, "parallel port"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_MULSER, 1, "multiport serial"},
|
||||
{PCIC_SIMPLECOMM, PCIS_SIMPLECOMM_MODEM, 1, "generic modem"},
|
||||
{PCIC_BASEPERIPH, -1, 0, "base peripheral"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PIC, 1, "interrupt controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_DMA, 1, "DMA controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_TIMER, 1, "timer"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_RTC, 1, "realtime clock"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_PCIHOT, 1, "PCI hot-plug controller"},
|
||||
{PCIC_BASEPERIPH, PCIS_BASEPERIPH_SDHC, 1, "SD host controller"},
|
||||
{PCIC_INPUTDEV, -1, 1, "input device"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_KEYBOARD, 1, "keyboard"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_DIGITIZER,1, "digitizer"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_MOUSE, 1, "mouse"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_SCANNER, 1, "scanner"},
|
||||
{PCIC_INPUTDEV, PCIS_INPUTDEV_GAMEPORT, 1, "gameport"},
|
||||
{PCIC_DOCKING, -1, 1, "docking station"},
|
||||
{PCIC_PROCESSOR, -1, 1, "processor"},
|
||||
{PCIC_SERIALBUS, -1, 1, "serial bus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FW, 1, "FireWire"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_ACCESS, 1, "AccessBus"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SSA, 1, "SSA"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_USB, 1, "USB"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_FC, 1, "Fibre Channel"},
|
||||
{PCIC_SERIALBUS, PCIS_SERIALBUS_SMBUS, 0, "SMBus"},
|
||||
{PCIC_WIRELESS, -1, 1, "wireless controller"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_IRDA, 1, "iRDA"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_IR, 1, "IR"},
|
||||
{PCIC_WIRELESS, PCIS_WIRELESS_RF, 1, "RF"},
|
||||
{PCIC_INTELLIIO, -1, 1, "intelligent I/O controller"},
|
||||
{PCIC_INTELLIIO, PCIS_INTELLIIO_I2O, 1, "I2O"},
|
||||
{PCIC_SATCOM, -1, 1, "satellite communication"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_TV, 1, "sat TV"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_AUDIO, 1, "sat audio"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_VOICE, 1, "sat voice"},
|
||||
{PCIC_SATCOM, PCIS_SATCOM_DATA, 1, "sat data"},
|
||||
{PCIC_CRYPTO, -1, 1, "encrypt/decrypt"},
|
||||
{PCIC_CRYPTO, PCIS_CRYPTO_NETCOMP, 1, "network/computer crypto"},
|
||||
{PCIC_CRYPTO, PCIS_CRYPTO_ENTERTAIN, 1, "entertainment crypto"},
|
||||
{PCIC_DASP, -1, 0, "dasp"},
|
||||
{PCIC_DASP, PCIS_DASP_DPIO, 1, "DPIO module"},
|
||||
{0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
void
|
||||
pci_probe_nomatch(device_t dev, device_t child)
|
||||
{
|
||||
int i;
|
||||
int i, report;
|
||||
const char *cp, *scp;
|
||||
char *device;
|
||||
|
||||
/*
|
||||
* Look for a listing for this device in a loaded device database.
|
||||
*/
|
||||
report = 1;
|
||||
if ((device = pci_describe_device(child)) != NULL) {
|
||||
device_printf(dev, "<%s>", device);
|
||||
free(device, M_DEVBUF);
|
||||
@ -3763,19 +3784,25 @@ pci_probe_nomatch(device_t dev, device_t child)
|
||||
if (pci_nomatch_tab[i].class == pci_get_class(child)) {
|
||||
if (pci_nomatch_tab[i].subclass == -1) {
|
||||
cp = pci_nomatch_tab[i].desc;
|
||||
report = pci_nomatch_tab[i].report;
|
||||
} else if (pci_nomatch_tab[i].subclass ==
|
||||
pci_get_subclass(child)) {
|
||||
scp = pci_nomatch_tab[i].desc;
|
||||
report = pci_nomatch_tab[i].report;
|
||||
}
|
||||
}
|
||||
}
|
||||
device_printf(dev, "<%s%s%s>",
|
||||
cp ? cp : "",
|
||||
((cp != NULL) && (scp != NULL)) ? ", " : "",
|
||||
scp ? scp : "");
|
||||
if (report || bootverbose) {
|
||||
device_printf(dev, "<%s%s%s>",
|
||||
cp ? cp : "",
|
||||
((cp != NULL) && (scp != NULL)) ? ", " : "",
|
||||
scp ? scp : "");
|
||||
}
|
||||
}
|
||||
if (report || bootverbose) {
|
||||
printf(" at device %d.%d (no driver attached)\n",
|
||||
pci_get_slot(child), pci_get_function(child));
|
||||
}
|
||||
printf(" at device %d.%d (no driver attached)\n",
|
||||
pci_get_slot(child), pci_get_function(child));
|
||||
pci_cfg_save(child, device_get_ivars(child), 1);
|
||||
}
|
||||
|
||||
@ -4078,7 +4105,6 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid,
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
struct resource_list *rl = &dinfo->resources;
|
||||
struct resource_list_entry *rle;
|
||||
struct resource *res;
|
||||
struct pci_map *pm;
|
||||
pci_addr_t map, testval;
|
||||
@ -4151,23 +4177,16 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid,
|
||||
* Allocate enough resource, and then write back the
|
||||
* appropriate BAR for that resource.
|
||||
*/
|
||||
res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid,
|
||||
start, end, count, flags & ~RF_ACTIVE);
|
||||
resource_list_add(rl, type, *rid, start, end, count);
|
||||
res = resource_list_reserve(rl, dev, child, type, rid, start, end,
|
||||
count, flags & ~RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
resource_list_delete(rl, type, *rid);
|
||||
device_printf(child,
|
||||
"%#lx bytes of rid %#x res %d failed (%#lx, %#lx).\n",
|
||||
count, *rid, type, start, end);
|
||||
goto out;
|
||||
}
|
||||
resource_list_add(rl, type, *rid, start, end, count);
|
||||
rle = resource_list_find(rl, type, *rid);
|
||||
if (rle == NULL)
|
||||
panic("pci_reserve_map: unexpectedly can't find resource.");
|
||||
rle->res = res;
|
||||
rle->start = rman_get_start(res);
|
||||
rle->end = rman_get_end(res);
|
||||
rle->count = count;
|
||||
rle->flags = RLE_RESERVED;
|
||||
if (bootverbose)
|
||||
device_printf(child,
|
||||
"Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n",
|
||||
@ -4182,11 +4201,11 @@ struct resource *
|
||||
pci_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 pci_devinfo *dinfo = device_get_ivars(child);
|
||||
struct resource_list *rl = &dinfo->resources;
|
||||
struct pci_devinfo *dinfo;
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle;
|
||||
struct resource *res;
|
||||
pcicfgregs *cfg = &dinfo->cfg;
|
||||
pcicfgregs *cfg;
|
||||
|
||||
if (device_get_parent(child) != dev)
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
|
||||
@ -4195,6 +4214,9 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
/*
|
||||
* Perform lazy resource allocation
|
||||
*/
|
||||
dinfo = device_get_ivars(child);
|
||||
rl = &dinfo->resources;
|
||||
cfg = &dinfo->cfg;
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
/*
|
||||
@ -4249,6 +4271,41 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
start, end, count, flags));
|
||||
}
|
||||
|
||||
int
|
||||
pci_release_resource(device_t dev, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
struct pci_devinfo *dinfo;
|
||||
struct resource_list *rl;
|
||||
pcicfgregs *cfg;
|
||||
|
||||
if (device_get_parent(child) != dev)
|
||||
return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
|
||||
type, rid, r));
|
||||
|
||||
dinfo = device_get_ivars(child);
|
||||
cfg = &dinfo->cfg;
|
||||
#ifdef NEW_PCIB
|
||||
/*
|
||||
* PCI-PCI bridge I/O window resources are not BARs. For
|
||||
* those allocations just pass the request up the tree.
|
||||
*/
|
||||
if (cfg->hdrtype == PCIM_HDRTYPE_BRIDGE &&
|
||||
(type == SYS_RES_IOPORT || type == SYS_RES_MEMORY)) {
|
||||
switch (rid) {
|
||||
case PCIR_IOBASEL_1:
|
||||
case PCIR_MEMBASE_1:
|
||||
case PCIR_PMBASEL_1:
|
||||
return (bus_generic_release_resource(dev, child, type,
|
||||
rid, r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
rl = &dinfo->resources;
|
||||
return (resource_list_release(rl, dev, child, type, rid, r));
|
||||
}
|
||||
|
||||
int
|
||||
pci_activate_resource(device_t dev, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
|
@ -105,13 +105,12 @@ DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc));
|
||||
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL);
|
||||
|
||||
#ifdef NEW_PCIB
|
||||
/*
|
||||
* XXX Todo:
|
||||
* - properly handle the ISA enable bit. If it is set, we should change
|
||||
* the behavior of the I/O window resource and rman to not allocate the
|
||||
* blocked ranges (upper 768 bytes of each 1K in the first 64k of the
|
||||
* I/O port address space).
|
||||
*/
|
||||
SYSCTL_DECL(_hw_pci);
|
||||
|
||||
static int pci_clear_pcib;
|
||||
TUNABLE_INT("hw.pci.clear_pcib", &pci_clear_pcib);
|
||||
SYSCTL_INT(_hw_pci, OID_AUTO, clear_pcib, CTLFLAG_RDTUN, &pci_clear_pcib, 0,
|
||||
"Clear firmware-assigned resources for PCI-PCI bridge I/O windows.");
|
||||
|
||||
/*
|
||||
* Is a resource from a child device sub-allocated from one of our
|
||||
@ -191,10 +190,183 @@ pcib_write_windows(struct pcib_softc *sc, int mask)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used to reject I/O port allocations that conflict with an
|
||||
* ISA alias range.
|
||||
*/
|
||||
static int
|
||||
pcib_is_isa_range(struct pcib_softc *sc, u_long start, u_long end, u_long count)
|
||||
{
|
||||
u_long next_alias;
|
||||
|
||||
if (!(sc->bridgectl & PCIB_BCR_ISA_ENABLE))
|
||||
return (0);
|
||||
|
||||
/* Only check fixed ranges for overlap. */
|
||||
if (start + count - 1 != end)
|
||||
return (0);
|
||||
|
||||
/* ISA aliases are only in the lower 64KB of I/O space. */
|
||||
if (start >= 65536)
|
||||
return (0);
|
||||
|
||||
/* Check for overlap with 0x000 - 0x0ff as a special case. */
|
||||
if (start < 0x100)
|
||||
goto alias;
|
||||
|
||||
/*
|
||||
* If the start address is an alias, the range is an alias.
|
||||
* Otherwise, compute the start of the next alias range and
|
||||
* check if it is before the end of the candidate range.
|
||||
*/
|
||||
if ((start & 0x300) != 0)
|
||||
goto alias;
|
||||
next_alias = (start & ~0x3fful) | 0x100;
|
||||
if (next_alias <= end)
|
||||
goto alias;
|
||||
return (0);
|
||||
|
||||
alias:
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"I/O range %#lx-%#lx overlaps with an ISA alias\n", start,
|
||||
end);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
pcib_add_window_resources(struct pcib_window *w, struct resource **res,
|
||||
int count)
|
||||
{
|
||||
struct resource **newarray;
|
||||
int error, i;
|
||||
|
||||
newarray = malloc(sizeof(struct resource *) * (w->count + count),
|
||||
M_DEVBUF, M_WAITOK);
|
||||
if (w->res != NULL)
|
||||
bcopy(w->res, newarray, sizeof(struct resource *) * w->count);
|
||||
bcopy(res, newarray + w->count, sizeof(struct resource *) * count);
|
||||
free(w->res, M_DEVBUF);
|
||||
w->res = newarray;
|
||||
w->count += count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
error = rman_manage_region(&w->rman, rman_get_start(res[i]),
|
||||
rman_get_end(res[i]));
|
||||
if (error)
|
||||
panic("Failed to add resource to rman");
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (nonisa_callback)(u_long start, u_long end, void *arg);
|
||||
|
||||
static void
|
||||
pcib_walk_nonisa_ranges(u_long start, u_long end, nonisa_callback *cb,
|
||||
void *arg)
|
||||
{
|
||||
u_long next_end;
|
||||
|
||||
/*
|
||||
* If start is within an ISA alias range, move up to the start
|
||||
* of the next non-alias range. As a special case, addresses
|
||||
* in the range 0x000 - 0x0ff should also be skipped since
|
||||
* those are used for various system I/O devices in ISA
|
||||
* systems.
|
||||
*/
|
||||
if (start <= 65535) {
|
||||
if (start < 0x100 || (start & 0x300) != 0) {
|
||||
start &= ~0x3ff;
|
||||
start += 0x400;
|
||||
}
|
||||
}
|
||||
|
||||
/* ISA aliases are only in the lower 64KB of I/O space. */
|
||||
while (start <= MIN(end, 65535)) {
|
||||
next_end = MIN(start | 0xff, end);
|
||||
cb(start, next_end, arg);
|
||||
start += 0x400;
|
||||
}
|
||||
|
||||
if (start <= end)
|
||||
cb(start, end, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
count_ranges(u_long start, u_long end, void *arg)
|
||||
{
|
||||
int *countp;
|
||||
|
||||
countp = arg;
|
||||
(*countp)++;
|
||||
}
|
||||
|
||||
struct alloc_state {
|
||||
struct resource **res;
|
||||
struct pcib_softc *sc;
|
||||
int count, error;
|
||||
};
|
||||
|
||||
static void
|
||||
alloc_ranges(u_long start, u_long end, void *arg)
|
||||
{
|
||||
struct alloc_state *as;
|
||||
struct pcib_window *w;
|
||||
int rid;
|
||||
|
||||
as = arg;
|
||||
if (as->error != 0)
|
||||
return;
|
||||
|
||||
w = &as->sc->io;
|
||||
rid = w->reg;
|
||||
if (bootverbose)
|
||||
device_printf(as->sc->dev,
|
||||
"allocating non-ISA range %#lx-%#lx\n", start, end);
|
||||
as->res[as->count] = bus_alloc_resource(as->sc->dev, SYS_RES_IOPORT,
|
||||
&rid, start, end, end - start + 1, 0);
|
||||
if (as->res[as->count] == NULL)
|
||||
as->error = ENXIO;
|
||||
else
|
||||
as->count++;
|
||||
}
|
||||
|
||||
static int
|
||||
pcib_alloc_nonisa_ranges(struct pcib_softc *sc, u_long start, u_long end)
|
||||
{
|
||||
struct alloc_state as;
|
||||
int i, new_count;
|
||||
|
||||
/* First, see how many ranges we need. */
|
||||
new_count = 0;
|
||||
pcib_walk_nonisa_ranges(start, end, count_ranges, &new_count);
|
||||
|
||||
/* Second, allocate the ranges. */
|
||||
as.res = malloc(sizeof(struct resource *) * new_count, M_DEVBUF,
|
||||
M_WAITOK);
|
||||
as.sc = sc;
|
||||
as.count = 0;
|
||||
as.error = 0;
|
||||
pcib_walk_nonisa_ranges(start, end, alloc_ranges, &as);
|
||||
if (as.error != 0) {
|
||||
for (i = 0; i < as.count; i++)
|
||||
bus_release_resource(sc->dev, SYS_RES_IOPORT,
|
||||
sc->io.reg, as.res[i]);
|
||||
free(as.res, M_DEVBUF);
|
||||
return (as.error);
|
||||
}
|
||||
KASSERT(as.count == new_count, ("%s: count mismatch", __func__));
|
||||
|
||||
/* Third, add the ranges to the window. */
|
||||
pcib_add_window_resources(&sc->io, as.res, as.count);
|
||||
free(as.res, M_DEVBUF);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
int flags, pci_addr_t max_address)
|
||||
{
|
||||
struct resource *res;
|
||||
char buf[64];
|
||||
int error, rid;
|
||||
|
||||
@ -219,9 +391,15 @@ pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
"initial %s window has too many bits, ignoring\n", w->name);
|
||||
return;
|
||||
}
|
||||
rid = w->reg;
|
||||
w->res = bus_alloc_resource(sc->dev, type, &rid, w->base, w->limit,
|
||||
w->limit - w->base + 1, flags);
|
||||
if (type == SYS_RES_IOPORT && sc->bridgectl & PCIB_BCR_ISA_ENABLE)
|
||||
(void)pcib_alloc_nonisa_ranges(sc, w->base, w->limit);
|
||||
else {
|
||||
rid = w->reg;
|
||||
res = bus_alloc_resource(sc->dev, type, &rid, w->base, w->limit,
|
||||
w->limit - w->base + 1, flags);
|
||||
if (res != NULL)
|
||||
pcib_add_window_resources(w, &res, 1);
|
||||
}
|
||||
if (w->res == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"failed to allocate initial %s window: %#jx-%#jx\n",
|
||||
@ -232,11 +410,6 @@ pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
return;
|
||||
}
|
||||
pcib_activate_window(sc, type);
|
||||
|
||||
error = rman_manage_region(&w->rman, rman_get_start(w->res),
|
||||
rman_get_end(w->res));
|
||||
if (error)
|
||||
panic("Failed to initialize rman with resource");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -251,6 +424,19 @@ pcib_probe_windows(struct pcib_softc *sc)
|
||||
|
||||
dev = sc->dev;
|
||||
|
||||
if (pci_clear_pcib) {
|
||||
pci_write_config(dev, PCIR_IOBASEL_1, 0xff, 1);
|
||||
pci_write_config(dev, PCIR_IOBASEH_1, 0xffff, 2);
|
||||
pci_write_config(dev, PCIR_IOLIMITL_1, 0, 1);
|
||||
pci_write_config(dev, PCIR_IOLIMITH_1, 0, 2);
|
||||
pci_write_config(dev, PCIR_MEMBASE_1, 0xffff, 2);
|
||||
pci_write_config(dev, PCIR_MEMLIMIT_1, 0, 2);
|
||||
pci_write_config(dev, PCIR_PMBASEL_1, 0xffff, 2);
|
||||
pci_write_config(dev, PCIR_PMBASEH_1, 0xffffffff, 4);
|
||||
pci_write_config(dev, PCIR_PMLIMITL_1, 0, 2);
|
||||
pci_write_config(dev, PCIR_PMLIMITH_1, 0, 4);
|
||||
}
|
||||
|
||||
/* Determine if the I/O port window is implemented. */
|
||||
val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
|
||||
if (val == 0) {
|
||||
@ -543,6 +729,7 @@ pcib_attach_common(device_t dev)
|
||||
struct pcib_softc *sc;
|
||||
struct sysctl_ctx_list *sctx;
|
||||
struct sysctl_oid *soid;
|
||||
int comma;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
@ -671,10 +858,22 @@ pcib_attach_common(device_t dev)
|
||||
device_printf(dev, " prefetched decode 0x%jx-0x%jx\n",
|
||||
(uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit);
|
||||
#endif
|
||||
else
|
||||
device_printf(dev, " no prefetched decode\n");
|
||||
if (sc->flags & PCIB_SUBTRACTIVE)
|
||||
device_printf(dev, " Subtractively decoded bridge.\n");
|
||||
if (sc->bridgectl & (PCIB_BCR_ISA_ENABLE | PCIB_BCR_VGA_ENABLE) ||
|
||||
sc->flags & PCIB_SUBTRACTIVE) {
|
||||
device_printf(dev, " special decode ");
|
||||
comma = 0;
|
||||
if (sc->bridgectl & PCIB_BCR_ISA_ENABLE) {
|
||||
printf("ISA");
|
||||
comma = 1;
|
||||
}
|
||||
if (sc->bridgectl & PCIB_BCR_VGA_ENABLE) {
|
||||
printf("%sVGA", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (sc->flags & PCIB_SUBTRACTIVE)
|
||||
printf("%ssubtractive", comma ? ", " : "");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -821,23 +1020,197 @@ pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w,
|
||||
return (res);
|
||||
}
|
||||
|
||||
/* Allocate a fresh resource range for an unconfigured window. */
|
||||
static int
|
||||
pcib_alloc_new_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct resource *res;
|
||||
u_long base, limit, wmask;
|
||||
int rid;
|
||||
|
||||
/*
|
||||
* If this is an I/O window on a bridge with ISA enable set
|
||||
* and the start address is below 64k, then try to allocate an
|
||||
* initial window of 0x1000 bytes long starting at address
|
||||
* 0xf000 and walking down. Note that if the original request
|
||||
* was larger than the non-aliased range size of 0x100 our
|
||||
* caller would have raised the start address up to 64k
|
||||
* already.
|
||||
*/
|
||||
if (type == SYS_RES_IOPORT && sc->bridgectl & PCIB_BCR_ISA_ENABLE &&
|
||||
start < 65536) {
|
||||
for (base = 0xf000; (long)base >= 0; base -= 0x1000) {
|
||||
limit = base + 0xfff;
|
||||
|
||||
/*
|
||||
* Skip ranges that wouldn't work for the
|
||||
* original request. Note that the actual
|
||||
* window that overlaps are the non-alias
|
||||
* ranges within [base, limit], so this isn't
|
||||
* quite a simple comparison.
|
||||
*/
|
||||
if (start + count > limit - 0x400)
|
||||
continue;
|
||||
if (base == 0) {
|
||||
/*
|
||||
* The first open region for the window at
|
||||
* 0 is 0x400-0x4ff.
|
||||
*/
|
||||
if (end - count + 1 < 0x400)
|
||||
continue;
|
||||
} else {
|
||||
if (end - count + 1 < base)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pcib_alloc_nonisa_ranges(sc, base, limit) == 0) {
|
||||
w->base = base;
|
||||
w->limit = limit;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (ENOSPC);
|
||||
}
|
||||
|
||||
wmask = (1ul << w->step) - 1;
|
||||
if (RF_ALIGNMENT(flags) < w->step) {
|
||||
flags &= ~RF_ALIGNMENT_MASK;
|
||||
flags |= RF_ALIGNMENT_LOG2(w->step);
|
||||
}
|
||||
start &= ~wmask;
|
||||
end |= wmask;
|
||||
count = roundup2(count, 1ul << w->step);
|
||||
rid = w->reg;
|
||||
res = bus_alloc_resource(sc->dev, type, &rid, start, end, count,
|
||||
flags & ~RF_ACTIVE);
|
||||
if (res == NULL)
|
||||
return (ENOSPC);
|
||||
pcib_add_window_resources(w, &res, 1);
|
||||
pcib_activate_window(sc, type);
|
||||
w->base = rman_get_start(res);
|
||||
w->limit = rman_get_end(res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Try to expand an existing window to the requested base and limit. */
|
||||
static int
|
||||
pcib_expand_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
u_long base, u_long limit)
|
||||
{
|
||||
struct resource *res;
|
||||
int error, i, force_64k_base;
|
||||
|
||||
KASSERT(base <= w->base && limit >= w->limit,
|
||||
("attempting to shrink window"));
|
||||
|
||||
/*
|
||||
* XXX: pcib_grow_window() doesn't try to do this anyway and
|
||||
* the error handling for all the edge cases would be tedious.
|
||||
*/
|
||||
KASSERT(limit == w->limit || base == w->base,
|
||||
("attempting to grow both ends of a window"));
|
||||
|
||||
/*
|
||||
* Yet more special handling for requests to expand an I/O
|
||||
* window behind an ISA-enabled bridge. Since I/O windows
|
||||
* have to grow in 0x1000 increments and the end of the 0xffff
|
||||
* range is an alias, growing a window below 64k will always
|
||||
* result in allocating new resources and never adjusting an
|
||||
* existing resource.
|
||||
*/
|
||||
if (type == SYS_RES_IOPORT && sc->bridgectl & PCIB_BCR_ISA_ENABLE &&
|
||||
(limit <= 65535 || (base <= 65535 && base != w->base))) {
|
||||
KASSERT(limit == w->limit || limit <= 65535,
|
||||
("attempting to grow both ends across 64k ISA alias"));
|
||||
|
||||
if (base != w->base)
|
||||
error = pcib_alloc_nonisa_ranges(sc, base, w->base - 1);
|
||||
else
|
||||
error = pcib_alloc_nonisa_ranges(sc, w->limit + 1,
|
||||
limit);
|
||||
if (error == 0) {
|
||||
w->base = base;
|
||||
w->limit = limit;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the existing resource to adjust. Usually there is only one,
|
||||
* but for an ISA-enabled bridge we might be growing the I/O window
|
||||
* above 64k and need to find the existing resource that maps all
|
||||
* of the area above 64k.
|
||||
*/
|
||||
for (i = 0; i < w->count; i++) {
|
||||
if (rman_get_end(w->res[i]) == w->limit)
|
||||
break;
|
||||
}
|
||||
KASSERT(i != w->count, ("did not find existing resource"));
|
||||
res = w->res[i];
|
||||
|
||||
/*
|
||||
* Usually the resource we found should match the window's
|
||||
* existing range. The one exception is the ISA-enabled case
|
||||
* mentioned above in which case the resource should start at
|
||||
* 64k.
|
||||
*/
|
||||
if (type == SYS_RES_IOPORT && sc->bridgectl & PCIB_BCR_ISA_ENABLE &&
|
||||
w->base <= 65535) {
|
||||
KASSERT(rman_get_start(res) == 65536,
|
||||
("existing resource mismatch"));
|
||||
force_64k_base = 1;
|
||||
} else {
|
||||
KASSERT(w->base == rman_get_start(res),
|
||||
("existing resource mismatch"));
|
||||
force_64k_base = 0;
|
||||
}
|
||||
|
||||
error = bus_adjust_resource(sc->dev, type, res, force_64k_base ?
|
||||
rman_get_start(res) : base, limit);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Add the newly allocated region to the resource manager. */
|
||||
if (w->base != base) {
|
||||
error = rman_manage_region(&w->rman, base, w->base - 1);
|
||||
w->base = base;
|
||||
} else {
|
||||
error = rman_manage_region(&w->rman, w->limit + 1, limit);
|
||||
w->limit = limit;
|
||||
}
|
||||
if (error) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"failed to expand %s resource manager\n", w->name);
|
||||
(void)bus_adjust_resource(sc->dev, type, res, force_64k_base ?
|
||||
rman_get_start(res) : w->base, w->limit);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to grow a window to make room for a given resource request.
|
||||
* The 'step' parameter is log_2 of the desired I/O window's alignment.
|
||||
*/
|
||||
static int
|
||||
pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
u_long align, start_free, end_free, front, back, wmask;
|
||||
int error, rid;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Clamp the desired resource range to the maximum address
|
||||
* this window supports. Reject impossible requests.
|
||||
*
|
||||
* For I/O port requests behind a bridge with the ISA enable
|
||||
* bit set, force large allocations to start above 64k.
|
||||
*/
|
||||
if (!w->valid)
|
||||
return (EINVAL);
|
||||
if (sc->bridgectl & PCIB_BCR_ISA_ENABLE && count > 0x100 &&
|
||||
start < 65536)
|
||||
start = 65536;
|
||||
if (end > w->rman.rm_end)
|
||||
end = w->rman.rm_end;
|
||||
if (start + count - 1 > end || start + count < start)
|
||||
@ -849,40 +1222,19 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
* aligned space for this resource.
|
||||
*/
|
||||
if (w->res == NULL) {
|
||||
if (RF_ALIGNMENT(flags) < w->step) {
|
||||
flags &= ~RF_ALIGNMENT_MASK;
|
||||
flags |= RF_ALIGNMENT_LOG2(w->step);
|
||||
}
|
||||
start &= ~wmask;
|
||||
end |= wmask;
|
||||
count = roundup2(count, 1ul << w->step);
|
||||
rid = w->reg;
|
||||
w->res = bus_alloc_resource(sc->dev, type, &rid, start, end,
|
||||
count, flags & ~RF_ACTIVE);
|
||||
if (w->res == NULL) {
|
||||
error = pcib_alloc_new_window(sc, w, type, start, end, count,
|
||||
flags);
|
||||
if (error) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"failed to allocate initial %s window (%#lx-%#lx,%#lx)\n",
|
||||
w->name, start, end, count);
|
||||
return (ENXIO);
|
||||
return (error);
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"allocated initial %s window of %#lx-%#lx\n",
|
||||
w->name, rman_get_start(w->res),
|
||||
rman_get_end(w->res));
|
||||
error = rman_manage_region(&w->rman, rman_get_start(w->res),
|
||||
rman_get_end(w->res));
|
||||
if (error) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"failed to add initial %s window to rman\n",
|
||||
w->name);
|
||||
bus_release_resource(sc->dev, type, w->reg, w->res);
|
||||
w->res = NULL;
|
||||
return (error);
|
||||
}
|
||||
pcib_activate_window(sc, type);
|
||||
"allocated initial %s window of %#jx-%#jx\n",
|
||||
w->name, (uintmax_t)w->base, (uintmax_t)w->limit);
|
||||
goto updatewin;
|
||||
}
|
||||
|
||||
@ -896,6 +1248,11 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
* edge of the window, grow from the inner edge of the free
|
||||
* region. Otherwise grow from the window boundary.
|
||||
*
|
||||
* Growing an I/O window below 64k for a bridge with the ISA
|
||||
* enable bit doesn't require any special magic as the step
|
||||
* size of an I/O window (1k) always includes multiple
|
||||
* non-alias ranges when it is grown in either direction.
|
||||
*
|
||||
* XXX: Special case: if w->res is completely empty and the
|
||||
* request size is larger than w->res, we should find the
|
||||
* optimal aligned buffer containing w->res and allocate that.
|
||||
@ -905,10 +1262,10 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
"attempting to grow %s window for (%#lx-%#lx,%#lx)\n",
|
||||
w->name, start, end, count);
|
||||
align = 1ul << RF_ALIGNMENT(flags);
|
||||
if (start < rman_get_start(w->res)) {
|
||||
if (start < w->base) {
|
||||
if (rman_first_free_region(&w->rman, &start_free, &end_free) !=
|
||||
0 || start_free != rman_get_start(w->res))
|
||||
end_free = rman_get_start(w->res);
|
||||
0 || start_free != w->base)
|
||||
end_free = w->base;
|
||||
if (end_free > end)
|
||||
end_free = end + 1;
|
||||
|
||||
@ -929,15 +1286,15 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
printf("\tfront candidate range: %#lx-%#lx\n",
|
||||
front, end_free);
|
||||
front &= ~wmask;
|
||||
front = rman_get_start(w->res) - front;
|
||||
front = w->base - front;
|
||||
} else
|
||||
front = 0;
|
||||
} else
|
||||
front = 0;
|
||||
if (end > rman_get_end(w->res)) {
|
||||
if (end > w->limit) {
|
||||
if (rman_last_free_region(&w->rman, &start_free, &end_free) !=
|
||||
0 || end_free != rman_get_end(w->res))
|
||||
start_free = rman_get_end(w->res) + 1;
|
||||
0 || end_free != w->limit)
|
||||
start_free = w->limit + 1;
|
||||
if (start_free < start)
|
||||
start_free = start;
|
||||
|
||||
@ -957,7 +1314,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
printf("\tback candidate range: %#lx-%#lx\n",
|
||||
start_free, back);
|
||||
back |= wmask;
|
||||
back -= rman_get_end(w->res);
|
||||
back -= w->limit;
|
||||
} else
|
||||
back = 0;
|
||||
} else
|
||||
@ -970,16 +1327,14 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
error = ENOSPC;
|
||||
while (front != 0 || back != 0) {
|
||||
if (front != 0 && (front <= back || back == 0)) {
|
||||
error = bus_adjust_resource(sc->dev, type, w->res,
|
||||
rman_get_start(w->res) - front,
|
||||
rman_get_end(w->res));
|
||||
error = pcib_expand_window(sc, w, type, w->base - front,
|
||||
w->limit);
|
||||
if (error == 0)
|
||||
break;
|
||||
front = 0;
|
||||
} else {
|
||||
error = bus_adjust_resource(sc->dev, type, w->res,
|
||||
rman_get_start(w->res),
|
||||
rman_get_end(w->res) + back);
|
||||
error = pcib_expand_window(sc, w, type, w->base,
|
||||
w->limit + back);
|
||||
if (error == 0)
|
||||
break;
|
||||
back = 0;
|
||||
@ -989,32 +1344,11 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
|
||||
if (error)
|
||||
return (error);
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "grew %s window to %#lx-%#lx\n",
|
||||
w->name, rman_get_start(w->res), rman_get_end(w->res));
|
||||
|
||||
/* Add the newly allocated region to the resource manager. */
|
||||
if (w->base != rman_get_start(w->res)) {
|
||||
KASSERT(w->limit == rman_get_end(w->res), ("both ends moved"));
|
||||
error = rman_manage_region(&w->rman, rman_get_start(w->res),
|
||||
w->base - 1);
|
||||
} else {
|
||||
KASSERT(w->limit != rman_get_end(w->res),
|
||||
("neither end moved"));
|
||||
error = rman_manage_region(&w->rman, w->limit + 1,
|
||||
rman_get_end(w->res));
|
||||
}
|
||||
if (error) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"failed to expand %s resource manager\n", w->name);
|
||||
bus_adjust_resource(sc->dev, type, w->res, w->base, w->limit);
|
||||
return (error);
|
||||
}
|
||||
device_printf(sc->dev, "grew %s window to %#jx-%#jx\n",
|
||||
w->name, (uintmax_t)w->base, (uintmax_t)w->limit);
|
||||
|
||||
updatewin:
|
||||
/* Save the new window. */
|
||||
w->base = rman_get_start(w->res);
|
||||
w->limit = rman_get_end(w->res);
|
||||
/* Write the new window. */
|
||||
KASSERT((w->base & wmask) == 0, ("start address is not aligned"));
|
||||
KASSERT((w->limit & wmask) == wmask, ("end address is not aligned"));
|
||||
pcib_write_windows(sc, w->mask);
|
||||
@ -1050,6 +1384,8 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
|
||||
switch (type) {
|
||||
case SYS_RES_IOPORT:
|
||||
if (pcib_is_isa_range(sc, start, end, count))
|
||||
return (NULL);
|
||||
r = pcib_suballoc_resource(sc, &sc->io, child, type, rid, start,
|
||||
end, count, flags);
|
||||
if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0)
|
||||
|
@ -91,6 +91,8 @@ int pci_msix_count_method(device_t dev, device_t child);
|
||||
struct resource *pci_alloc_resource(device_t dev, device_t child,
|
||||
int type, int *rid, u_long start, u_long end, u_long count,
|
||||
u_int flags);
|
||||
int pci_release_resource(device_t dev, device_t child, int type,
|
||||
int rid, struct resource *r);
|
||||
int pci_activate_resource(device_t dev, device_t child, int type,
|
||||
int rid, struct resource *r);
|
||||
int pci_deactivate_resource(device_t dev, device_t child, int type,
|
||||
|
@ -408,6 +408,89 @@ pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches,
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
#endif /* PRE7_COMPAT */
|
||||
|
||||
static int
|
||||
pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio)
|
||||
{
|
||||
struct pci_vpd_element vpd_element, *vpd_user;
|
||||
struct pcicfg_vpd *vpd;
|
||||
size_t len;
|
||||
int error, i;
|
||||
|
||||
vpd = pci_fetch_vpd_list(dev);
|
||||
if (vpd->vpd_reg == 0 || vpd->vpd_ident == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* Calculate the amount of space needed in the data buffer. An
|
||||
* identifier element is always present followed by the read-only
|
||||
* and read-write keywords.
|
||||
*/
|
||||
len = sizeof(struct pci_vpd_element) + strlen(vpd->vpd_ident);
|
||||
for (i = 0; i < vpd->vpd_rocnt; i++)
|
||||
len += sizeof(struct pci_vpd_element) + vpd->vpd_ros[i].len;
|
||||
for (i = 0; i < vpd->vpd_wcnt; i++)
|
||||
len += sizeof(struct pci_vpd_element) + vpd->vpd_w[i].len;
|
||||
|
||||
if (lvio->plvi_len == 0) {
|
||||
lvio->plvi_len = len;
|
||||
return (0);
|
||||
}
|
||||
if (lvio->plvi_len < len) {
|
||||
lvio->plvi_len = len;
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyout the identifier string followed by each keyword and
|
||||
* value.
|
||||
*/
|
||||
vpd_user = lvio->plvi_data;
|
||||
vpd_element.pve_keyword[0] = '\0';
|
||||
vpd_element.pve_keyword[1] = '\0';
|
||||
vpd_element.pve_flags = PVE_FLAG_IDENT;
|
||||
vpd_element.pve_datalen = strlen(vpd->vpd_ident);
|
||||
error = copyout(&vpd_element, vpd_user, sizeof(vpd_element));
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyout(vpd->vpd_ident, vpd_user->pve_data,
|
||||
strlen(vpd->vpd_ident));
|
||||
if (error)
|
||||
return (error);
|
||||
vpd_user = PVE_NEXT(vpd_user);
|
||||
vpd_element.pve_flags = 0;
|
||||
for (i = 0; i < vpd->vpd_rocnt; i++) {
|
||||
vpd_element.pve_keyword[0] = vpd->vpd_ros[i].keyword[0];
|
||||
vpd_element.pve_keyword[1] = vpd->vpd_ros[i].keyword[1];
|
||||
vpd_element.pve_datalen = vpd->vpd_ros[i].len;
|
||||
error = copyout(&vpd_element, vpd_user, sizeof(vpd_element));
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyout(vpd->vpd_ros[i].value, vpd_user->pve_data,
|
||||
vpd->vpd_ros[i].len);
|
||||
if (error)
|
||||
return (error);
|
||||
vpd_user = PVE_NEXT(vpd_user);
|
||||
}
|
||||
vpd_element.pve_flags = PVE_FLAG_RW;
|
||||
for (i = 0; i < vpd->vpd_wcnt; i++) {
|
||||
vpd_element.pve_keyword[0] = vpd->vpd_w[i].keyword[0];
|
||||
vpd_element.pve_keyword[1] = vpd->vpd_w[i].keyword[1];
|
||||
vpd_element.pve_datalen = vpd->vpd_w[i].len;
|
||||
error = copyout(&vpd_element, vpd_user, sizeof(vpd_element));
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyout(vpd->vpd_w[i].value, vpd_user->pve_data,
|
||||
vpd->vpd_w[i].len);
|
||||
if (error)
|
||||
return (error);
|
||||
vpd_user = PVE_NEXT(vpd_user);
|
||||
}
|
||||
KASSERT((char *)vpd_user - (char *)lvio->plvi_data == len,
|
||||
("length mismatch"));
|
||||
lvio->plvi_len = len;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
@ -419,6 +502,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
|
||||
struct pci_devinfo *dinfo;
|
||||
struct pci_io *io;
|
||||
struct pci_bar_io *bio;
|
||||
struct pci_list_vpd_io *lvio;
|
||||
struct pci_match_conf *pattern_buf;
|
||||
struct pci_map *pm;
|
||||
size_t confsz, iolen, pbufsz;
|
||||
@ -435,19 +519,29 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
|
||||
struct pci_match_conf_old *pattern_buf_old = NULL;
|
||||
|
||||
io_old = NULL;
|
||||
|
||||
if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
|
||||
cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
|
||||
return EPERM;
|
||||
#else
|
||||
if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF)
|
||||
return EPERM;
|
||||
#endif
|
||||
|
||||
switch(cmd) {
|
||||
if (!(flag & FWRITE)) {
|
||||
switch (cmd) {
|
||||
#ifdef PRE7_COMPAT
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
case PCIOCGETCONF_OLD32:
|
||||
case PCIOCGETCONF_OLD32:
|
||||
#endif
|
||||
case PCIOCGETCONF_OLD:
|
||||
#endif
|
||||
case PCIOCGETCONF:
|
||||
case PCIOCGETBAR:
|
||||
case PCIOCLISTVPD:
|
||||
break;
|
||||
default:
|
||||
return (EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef PRE7_COMPAT
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
case PCIOCGETCONF_OLD32:
|
||||
cio32 = (struct pci_conf_io32 *)data;
|
||||
cio = malloc(sizeof(struct pci_conf_io), M_TEMP, M_WAITOK);
|
||||
cio->pat_buf_len = cio32->pat_buf_len;
|
||||
@ -468,7 +562,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
|
||||
cio = (struct pci_conf_io *)data;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
#ifdef PRE7_COMPAT
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
case PCIOCGETCONF_OLD32:
|
||||
@ -914,6 +1008,22 @@ getconfexit:
|
||||
else
|
||||
error = ENODEV;
|
||||
break;
|
||||
case PCIOCLISTVPD:
|
||||
lvio = (struct pci_list_vpd_io *)data;
|
||||
|
||||
/*
|
||||
* Assume that the user-level bus number is
|
||||
* in fact the physical PCI bus number.
|
||||
*/
|
||||
pcidev = pci_find_dbsf(lvio->plvi_sel.pc_domain,
|
||||
lvio->plvi_sel.pc_bus, lvio->plvi_sel.pc_dev,
|
||||
lvio->plvi_sel.pc_func);
|
||||
if (pcidev == NULL) {
|
||||
error = ENODEV;
|
||||
break;
|
||||
}
|
||||
error = pci_list_vpd(pcidev, lvio);
|
||||
break;
|
||||
default:
|
||||
error = ENOTTY;
|
||||
break;
|
||||
|
@ -73,7 +73,8 @@ struct pcib_window {
|
||||
pci_addr_t base; /* base address */
|
||||
pci_addr_t limit; /* topmost address */
|
||||
struct rman rman;
|
||||
struct resource *res;
|
||||
struct resource **res;
|
||||
int count; /* size of 'res' array */
|
||||
int reg; /* resource id from parent */
|
||||
int valid;
|
||||
int mask; /* WIN_* bitmask of this window */
|
||||
|
@ -752,8 +752,17 @@
|
||||
#define PCIEM_SLOT_STA_EIS 0x0080
|
||||
#define PCIEM_SLOT_STA_DLLSC 0x0100
|
||||
#define PCIER_ROOT_CTL 0x1c
|
||||
#define PCIEM_ROOT_CTL_SERR_CORR 0x0001
|
||||
#define PCIEM_ROOT_CTL_SERR_NONFATAL 0x0002
|
||||
#define PCIEM_ROOT_CTL_SERR_FATAL 0x0004
|
||||
#define PCIEM_ROOT_CTL_PME 0x0008
|
||||
#define PCIEM_ROOT_CTL_CRS_VIS 0x0010
|
||||
#define PCIER_ROOT_CAP 0x1e
|
||||
#define PCIEM_ROOT_CAP_CRS_VIS 0x0001
|
||||
#define PCIER_ROOT_STA 0x20
|
||||
#define PCIEM_ROOT_STA_PME_REQID_MASK 0x0000ffff
|
||||
#define PCIEM_ROOT_STA_PME_STATUS 0x00010000
|
||||
#define PCIEM_ROOT_STA_PME_PEND 0x00020000
|
||||
#define PCIER_DEVICE_CAP2 0x24
|
||||
#define PCIER_DEVICE_CTL2 0x28
|
||||
#define PCIEM_CTL2_COMP_TIMEOUT_VAL 0x000f
|
||||
|
@ -57,6 +57,7 @@ struct pci_map {
|
||||
struct vpd_readonly {
|
||||
char keyword[2];
|
||||
char *value;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct vpd_write {
|
||||
@ -491,5 +492,13 @@ extern uint32_t pci_generation;
|
||||
|
||||
struct pci_map *pci_find_bar(device_t dev, int reg);
|
||||
int pci_bar_enabled(device_t dev, struct pci_map *pm);
|
||||
struct pcicfg_vpd *pci_fetch_vpd_list(device_t dev);
|
||||
|
||||
#define VGA_PCI_BIOS_SHADOW_ADDR 0xC0000
|
||||
#define VGA_PCI_BIOS_SHADOW_SIZE 131072
|
||||
|
||||
int vga_pci_is_boot_display(device_t dev);
|
||||
void * vga_pci_map_bios(device_t dev, size_t *size);
|
||||
void vga_pci_unmap_bios(device_t dev, void *bios);
|
||||
|
||||
#endif /* _PCIVAR_H_ */
|
||||
|
@ -183,7 +183,7 @@ static const struct rl_type re_devs[] = {
|
||||
{ RT_VENDORID, RT_DEVICEID_8101E, 0,
|
||||
"RealTek 810xE PCIe 10/100baseTX" },
|
||||
{ RT_VENDORID, RT_DEVICEID_8168, 0,
|
||||
"RealTek 8168/8111 B/C/CP/D/DP/E/F PCIe Gigabit Ethernet" },
|
||||
"RealTek 8168/8111 B/C/CP/D/DP/E/F/G PCIe Gigabit Ethernet" },
|
||||
{ RT_VENDORID, RT_DEVICEID_8169, 0,
|
||||
"RealTek 8169/8169S/8169SB(L)/8110S/8110SB(L) Gigabit Ethernet" },
|
||||
{ RT_VENDORID, RT_DEVICEID_8169SC, 0,
|
||||
@ -225,6 +225,7 @@ static const struct rl_hwrev re_hwrevs[] = {
|
||||
{ RL_HWREV_8402, RL_8169, "8402", RL_MTU },
|
||||
{ RL_HWREV_8105E, RL_8169, "8105E", RL_MTU },
|
||||
{ RL_HWREV_8105E_SPIN1, RL_8169, "8105E", RL_MTU },
|
||||
{ RL_HWREV_8106E, RL_8169, "8106E", RL_MTU },
|
||||
{ RL_HWREV_8168B_SPIN2, RL_8169, "8168", RL_JUMBO_MTU },
|
||||
{ RL_HWREV_8168B_SPIN3, RL_8169, "8168", RL_JUMBO_MTU },
|
||||
{ RL_HWREV_8168C, RL_8169, "8168C/8111C", RL_JUMBO_MTU_6K },
|
||||
@ -234,8 +235,12 @@ static const struct rl_hwrev re_hwrevs[] = {
|
||||
{ RL_HWREV_8168DP, RL_8169, "8168DP/8111DP", RL_JUMBO_MTU_9K },
|
||||
{ RL_HWREV_8168E, RL_8169, "8168E/8111E", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8168E_VL, RL_8169, "8168E/8111E-VL", RL_JUMBO_MTU_6K},
|
||||
{ RL_HWREV_8168EP, RL_8169, "8168EP/8111EP", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8168F, RL_8169, "8168F/8111F", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8168G, RL_8169, "8168G/8111G", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8168GU, RL_8169, "8168GU/8111GU", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8411, RL_8169, "8411", RL_JUMBO_MTU_9K},
|
||||
{ RL_HWREV_8411B, RL_8169, "8411B", RL_JUMBO_MTU_9K},
|
||||
{ 0, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -652,6 +657,10 @@ re_set_rxmode(struct rl_softc *sc)
|
||||
ifp = sc->rl_ifp;
|
||||
|
||||
rxfilt = RL_RXCFG_CONFIG | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_BROAD;
|
||||
if ((sc->rl_flags & RL_FLAG_EARLYOFF) != 0)
|
||||
rxfilt |= RL_RXCFG_EARLYOFF;
|
||||
else if ((sc->rl_flags & RL_FLAG_EARLYOFFV2) != 0)
|
||||
rxfilt |= RL_RXCFG_EARLYOFFV2;
|
||||
|
||||
if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
|
||||
if (ifp->if_flags & IFF_PROMISC)
|
||||
@ -1261,7 +1270,7 @@ re_attach(device_t dev)
|
||||
msic = 0;
|
||||
/* Prefer MSI-X to MSI. */
|
||||
if (msixc > 0) {
|
||||
msixc = 1;
|
||||
msixc = RL_MSI_MESSAGES;
|
||||
rid = PCIR_BAR(4);
|
||||
sc->rl_res_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, RF_ACTIVE);
|
||||
@ -1271,7 +1280,7 @@ re_attach(device_t dev)
|
||||
}
|
||||
if (sc->rl_res_pba != NULL &&
|
||||
pci_alloc_msix(dev, &msixc) == 0) {
|
||||
if (msixc == 1) {
|
||||
if (msixc == RL_MSI_MESSAGES) {
|
||||
device_printf(dev, "Using %d MSI-X message\n",
|
||||
msixc);
|
||||
sc->rl_flags |= RL_FLAG_MSIX;
|
||||
@ -1288,7 +1297,7 @@ re_attach(device_t dev)
|
||||
}
|
||||
/* Prefer MSI to INTx. */
|
||||
if (msixc == 0 && msic > 0) {
|
||||
msic = 1;
|
||||
msic = RL_MSI_MESSAGES;
|
||||
if (pci_alloc_msi(dev, &msic) == 0) {
|
||||
if (msic == RL_MSI_MESSAGES) {
|
||||
device_printf(dev, "Using %d MSI message\n",
|
||||
@ -1369,10 +1378,11 @@ re_attach(device_t dev)
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "Chip rev. 0x%08x\n", hwrev & 0x7c800000);
|
||||
sc->rl_macrev = hwrev & 0x00700000;
|
||||
hwrev &= RL_TXCFG_HWREV;
|
||||
break;
|
||||
}
|
||||
device_printf(dev, "MAC rev. 0x%08x\n", hwrev & 0x00700000);
|
||||
device_printf(dev, "MAC rev. 0x%08x\n", sc->rl_macrev);
|
||||
while (hw_rev->rl_desc != NULL) {
|
||||
if (hw_rev->rl_rev == hwrev) {
|
||||
sc->rl_type = hw_rev->rl_type;
|
||||
@ -1410,6 +1420,7 @@ re_attach(device_t dev)
|
||||
case RL_HWREV_8401E:
|
||||
case RL_HWREV_8105E:
|
||||
case RL_HWREV_8105E_SPIN1:
|
||||
case RL_HWREV_8106E:
|
||||
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
|
||||
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
|
||||
RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD;
|
||||
@ -1431,7 +1442,7 @@ re_attach(device_t dev)
|
||||
sc->rl_flags |= RL_FLAG_MACSLEEP;
|
||||
/* FALLTHROUGH */
|
||||
case RL_HWREV_8168C:
|
||||
if ((hwrev & 0x00700000) == 0x00200000)
|
||||
if (sc->rl_macrev == 0x00200000)
|
||||
sc->rl_flags |= RL_FLAG_MACSLEEP;
|
||||
/* FALLTHROUGH */
|
||||
case RL_HWREV_8168CP:
|
||||
@ -1458,12 +1469,35 @@ re_attach(device_t dev)
|
||||
break;
|
||||
case RL_HWREV_8168E_VL:
|
||||
case RL_HWREV_8168F:
|
||||
sc->rl_flags |= RL_FLAG_EARLYOFF;
|
||||
/* FALLTHROUGH */
|
||||
case RL_HWREV_8411:
|
||||
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
|
||||
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
|
||||
RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
|
||||
RL_FLAG_CMDSTOP_WAIT_TXQ | RL_FLAG_WOL_MANLINK;
|
||||
break;
|
||||
case RL_HWREV_8168EP:
|
||||
case RL_HWREV_8168G:
|
||||
case RL_HWREV_8411B:
|
||||
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
|
||||
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
|
||||
RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
|
||||
RL_FLAG_CMDSTOP_WAIT_TXQ | RL_FLAG_WOL_MANLINK |
|
||||
RL_FLAG_EARLYOFFV2 | RL_FLAG_RXDV_GATED;
|
||||
break;
|
||||
case RL_HWREV_8168GU:
|
||||
if (pci_get_device(dev) == RT_DEVICEID_8101E) {
|
||||
/* RTL8106EUS */
|
||||
sc->rl_flags |= RL_FLAG_FASTETHER;
|
||||
} else
|
||||
sc->rl_flags |= RL_FLAG_JUMBOV2 | RL_FLAG_WOL_MANLINK;
|
||||
|
||||
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
|
||||
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
|
||||
RL_FLAG_AUTOPAD | RL_FLAG_CMDSTOP_WAIT_TXQ |
|
||||
RL_FLAG_EARLYOFFV2 | RL_FLAG_RXDV_GATED;
|
||||
break;
|
||||
case RL_HWREV_8169_8110SB:
|
||||
case RL_HWREV_8169_8110SBL:
|
||||
case RL_HWREV_8169_8110SC:
|
||||
@ -1586,16 +1620,18 @@ re_attach(device_t dev)
|
||||
ifp->if_start = re_start;
|
||||
/*
|
||||
* RTL8168/8111C generates wrong IP checksummed frame if the
|
||||
* packet has IP options so disable TX IP checksum offloading.
|
||||
* packet has IP options so disable TX checksum offloading.
|
||||
*/
|
||||
if (sc->rl_hwrev->rl_rev == RL_HWREV_8168C ||
|
||||
sc->rl_hwrev->rl_rev == RL_HWREV_8168C_SPIN2 ||
|
||||
sc->rl_hwrev->rl_rev == RL_HWREV_8168CP)
|
||||
ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
|
||||
else
|
||||
sc->rl_hwrev->rl_rev == RL_HWREV_8168CP) {
|
||||
ifp->if_hwassist = 0;
|
||||
ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_TSO4;
|
||||
} else {
|
||||
ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP;
|
||||
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_TSO4;
|
||||
}
|
||||
ifp->if_hwassist |= CSUM_TSO;
|
||||
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_TSO4;
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
ifp->if_init = re_init;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, RL_IFQ_MAXLEN);
|
||||
@ -2114,8 +2150,7 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp)
|
||||
|
||||
ifp = sc->rl_ifp;
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_rx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT),
|
||||
&rx_npkts))
|
||||
if (netmap_rx_irq(ifp, 0, &rx_npkts))
|
||||
return 0;
|
||||
#endif /* DEV_NETMAP */
|
||||
if (ifp->if_mtu > RL_MTU && (sc->rl_flags & RL_FLAG_JUMBOV2) != 0)
|
||||
@ -2360,7 +2395,7 @@ re_txeof(struct rl_softc *sc)
|
||||
|
||||
ifp = sc->rl_ifp;
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT)))
|
||||
if (netmap_tx_irq(ifp, 0))
|
||||
return;
|
||||
#endif /* DEV_NETMAP */
|
||||
/* Invalidate the TX descriptor list */
|
||||
@ -3151,6 +3186,10 @@ re_init_locked(struct rl_softc *sc)
|
||||
CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO,
|
||||
RL_ADDR_LO(sc->rl_ldata.rl_tx_list_addr));
|
||||
|
||||
if ((sc->rl_flags & RL_FLAG_RXDV_GATED) != 0)
|
||||
CSR_WRITE_4(sc, RL_MISC, CSR_READ_4(sc, RL_MISC) &
|
||||
~0x00080000);
|
||||
|
||||
/*
|
||||
* Enable transmit and receive.
|
||||
*/
|
||||
@ -3328,13 +3367,14 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
struct rl_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
struct mii_data *mii;
|
||||
uint32_t rev;
|
||||
int error = 0;
|
||||
|
||||
switch (command) {
|
||||
case SIOCSIFMTU:
|
||||
if (ifr->ifr_mtu < ETHERMIN ||
|
||||
ifr->ifr_mtu > sc->rl_hwrev->rl_max_mtu) {
|
||||
ifr->ifr_mtu > sc->rl_hwrev->rl_max_mtu ||
|
||||
((sc->rl_flags & RL_FLAG_FASTETHER) != 0 &&
|
||||
ifr->ifr_mtu > RL_MTU)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -3415,15 +3455,9 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
if ((mask & IFCAP_TXCSUM) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
|
||||
ifp->if_capenable ^= IFCAP_TXCSUM;
|
||||
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) {
|
||||
rev = sc->rl_hwrev->rl_rev;
|
||||
if (rev == RL_HWREV_8168C ||
|
||||
rev == RL_HWREV_8168C_SPIN2 ||
|
||||
rev == RL_HWREV_8168CP)
|
||||
ifp->if_hwassist |= CSUM_TCP | CSUM_UDP;
|
||||
else
|
||||
ifp->if_hwassist |= RE_CSUM_FEATURES;
|
||||
} else
|
||||
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
|
||||
ifp->if_hwassist |= RE_CSUM_FEATURES;
|
||||
else
|
||||
ifp->if_hwassist &= ~RE_CSUM_FEATURES;
|
||||
reinit = 1;
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ ehci_init_sub(struct ehci_softc *sc)
|
||||
DPRINTF("HCC uses 64-bit structures\n");
|
||||
|
||||
/* MUST clear segment register if 64 bit capable */
|
||||
EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
|
||||
EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
|
||||
}
|
||||
|
||||
usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
|
||||
@ -1197,9 +1197,16 @@ ehci_non_isoc_done_sub(struct usb_xfer *xfer)
|
||||
(status & EHCI_QTD_PINGSTATE) ? "[PING]" : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
return ((status & EHCI_QTD_HALTED) ?
|
||||
USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
|
||||
if (status & EHCI_QTD_HALTED) {
|
||||
if ((xfer->xroot->udev->parent_hs_hub != NULL) ||
|
||||
(xfer->xroot->udev->address != 0)) {
|
||||
/* try to separate I/O errors from STALL */
|
||||
if (EHCI_QTD_GET_CERR(status) == 0)
|
||||
return (USB_ERR_IOERROR);
|
||||
}
|
||||
return (USB_ERR_STALLED);
|
||||
}
|
||||
return (USB_ERR_NORMAL_COMPLETION);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1653,12 +1660,17 @@ restart:
|
||||
}
|
||||
td->len = 0;
|
||||
|
||||
/* properly reset reserved fields */
|
||||
td->qtd_buffer[0] = 0;
|
||||
td->qtd_buffer_hi[0] = 0;
|
||||
|
||||
td->qtd_buffer[1] = 0;
|
||||
td->qtd_buffer[2] = 0;
|
||||
td->qtd_buffer[3] = 0;
|
||||
td->qtd_buffer[4] = 0;
|
||||
td->qtd_buffer_hi[0] = 0;
|
||||
td->qtd_buffer_hi[1] = 0;
|
||||
|
||||
td->qtd_buffer_hi[2] = 0;
|
||||
td->qtd_buffer_hi[3] = 0;
|
||||
td->qtd_buffer_hi[4] = 0;
|
||||
} else {
|
||||
|
||||
uint8_t x;
|
||||
@ -1713,6 +1725,12 @@ restart:
|
||||
htohc32(temp->sc,
|
||||
buf_res.physaddr & (~0xFFF));
|
||||
td->qtd_buffer_hi[x] = 0;
|
||||
|
||||
/* properly reset reserved fields */
|
||||
while (++x < EHCI_QTD_NBUFFERS) {
|
||||
td->qtd_buffer[x] = 0;
|
||||
td->qtd_buffer_hi[x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (td_next) {
|
||||
@ -2000,6 +2018,18 @@ ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last)
|
||||
qh->qh_qtd.qtd_altnext =
|
||||
htohc32(temp.sc, EHCI_LINK_TERMINATE);
|
||||
|
||||
/* properly reset reserved fields */
|
||||
qh->qh_qtd.qtd_buffer[0] = 0;
|
||||
qh->qh_qtd.qtd_buffer[1] = 0;
|
||||
qh->qh_qtd.qtd_buffer[2] = 0;
|
||||
qh->qh_qtd.qtd_buffer[3] = 0;
|
||||
qh->qh_qtd.qtd_buffer[4] = 0;
|
||||
qh->qh_qtd.qtd_buffer_hi[0] = 0;
|
||||
qh->qh_qtd.qtd_buffer_hi[1] = 0;
|
||||
qh->qh_qtd.qtd_buffer_hi[2] = 0;
|
||||
qh->qh_qtd.qtd_buffer_hi[3] = 0;
|
||||
qh->qh_qtd.qtd_buffer_hi[4] = 0;
|
||||
|
||||
usb_pc_cpu_flush(qh->page_cache);
|
||||
|
||||
if (xfer->xroot->udev->flags.self_suspended == 0) {
|
||||
@ -2229,11 +2259,27 @@ ehci_device_bulk_enter(struct usb_xfer *xfer)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_doorbell_async(struct ehci_softc *sc)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/*
|
||||
* XXX Performance quirk: Some Host Controllers have a too low
|
||||
* interrupt rate. Issue an IAAD to stimulate the Host
|
||||
* Controller after queueing the BULK transfer.
|
||||
*
|
||||
* XXX Force the host controller to refresh any QH caches.
|
||||
*/
|
||||
temp = EOREAD4(sc, EHCI_USBCMD);
|
||||
if (!(temp & EHCI_CMD_IAAD))
|
||||
EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_device_bulk_start(struct usb_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t temp;
|
||||
|
||||
/* setup TD's and QH */
|
||||
ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
|
||||
@ -2248,13 +2294,7 @@ ehci_device_bulk_start(struct usb_xfer *xfer)
|
||||
if (sc->sc_flags & EHCI_SCFLG_IAADBUG)
|
||||
return;
|
||||
|
||||
/* XXX Performance quirk: Some Host Controllers have a too low
|
||||
* interrupt rate. Issue an IAAD to stimulate the Host
|
||||
* Controller after queueing the BULK transfer.
|
||||
*/
|
||||
temp = EOREAD4(sc, EHCI_USBCMD);
|
||||
if (!(temp & EHCI_CMD_IAAD))
|
||||
EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
|
||||
ehci_doorbell_async(sc);
|
||||
}
|
||||
|
||||
struct usb_pipe_methods ehci_device_bulk_methods =
|
||||
@ -3707,10 +3747,6 @@ ehci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
|
||||
edesc->bEndpointAddress, udev->flags.usb_mode,
|
||||
sc->sc_addr);
|
||||
|
||||
if (udev->flags.usb_mode != USB_MODE_HOST) {
|
||||
/* not supported */
|
||||
return;
|
||||
}
|
||||
if (udev->device_index != sc->sc_addr) {
|
||||
|
||||
if ((udev->speed != USB_SPEED_HIGH) &&
|
||||
@ -3754,7 +3790,7 @@ ehci_get_dma_delay(struct usb_device *udev, uint32_t *pus)
|
||||
* Wait until the hardware has finished any possible use of
|
||||
* the transfer descriptor(s) and QH
|
||||
*/
|
||||
*pus = (188); /* microseconds */
|
||||
*pus = (1125); /* microseconds */
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3875,6 +3911,41 @@ ehci_set_hw_power(struct usb_bus *bus)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_start_dma_delay_second(struct usb_xfer *xfer)
|
||||
{
|
||||
struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
/* trigger doorbell */
|
||||
ehci_doorbell_async(sc);
|
||||
|
||||
/* give the doorbell 4ms */
|
||||
usbd_transfer_timeout_ms(xfer,
|
||||
(void (*)(void *))&usb_dma_delay_done_cb, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ring the doorbell twice before freeing any DMA descriptors. Some host
|
||||
* controllers apparently cache the QH descriptors and need a message
|
||||
* that the cache needs to be discarded.
|
||||
*/
|
||||
static void
|
||||
ehci_start_dma_delay(struct usb_xfer *xfer)
|
||||
{
|
||||
struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
/* trigger doorbell */
|
||||
ehci_doorbell_async(sc);
|
||||
|
||||
/* give the doorbell 4ms */
|
||||
usbd_transfer_timeout_ms(xfer,
|
||||
(void (*)(void *))&ehci_start_dma_delay_second, 4);
|
||||
}
|
||||
|
||||
struct usb_bus_methods ehci_bus_methods =
|
||||
{
|
||||
.endpoint_init = ehci_ep_init,
|
||||
@ -3887,4 +3958,5 @@ struct usb_bus_methods ehci_bus_methods =
|
||||
.set_hw_power_sleep = ehci_set_hw_power_sleep,
|
||||
.roothub_exec = ehci_roothub_exec,
|
||||
.xfer_poll = ehci_do_poll,
|
||||
.start_dma_delay = ehci_start_dma_delay,
|
||||
};
|
||||
|
@ -2316,6 +2316,7 @@ ohci_roothub_exec(struct usb_device *udev,
|
||||
}
|
||||
v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
|
||||
DPRINTFN(9, "port status=0x%04x\n", v);
|
||||
v &= ~UPS_PORT_MODE_DEVICE; /* force host mode */
|
||||
USETW(sc->sc_hub_desc.ps.wPortStatus, v);
|
||||
USETW(sc->sc_hub_desc.ps.wPortChange, v >> 16);
|
||||
len = sizeof(sc->sc_hub_desc.ps);
|
||||
@ -2552,10 +2553,6 @@ ohci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
|
||||
edesc->bEndpointAddress, udev->flags.usb_mode,
|
||||
sc->sc_addr);
|
||||
|
||||
if (udev->flags.usb_mode != USB_MODE_HOST) {
|
||||
/* not supported */
|
||||
return;
|
||||
}
|
||||
if (udev->device_index != sc->sc_addr) {
|
||||
switch (edesc->bmAttributes & UE_XFERTYPE) {
|
||||
case UE_CONTROL:
|
||||
|
@ -287,6 +287,28 @@ usb_resume(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bus_reset_async_locked
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb_bus_reset_async_locked(struct usb_bus *bus)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
if (bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL ||
|
||||
bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL) {
|
||||
DPRINTF("Reset already pending\n");
|
||||
return;
|
||||
}
|
||||
|
||||
device_printf(bus->parent, "Resetting controller\n");
|
||||
|
||||
usb_proc_msignal(&bus->explore_proc,
|
||||
&bus->reset_msg[0], &bus->reset_msg[1]);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_shutdown
|
||||
*------------------------------------------------------------------------*/
|
||||
@ -338,7 +360,13 @@ usb_bus_explore(struct usb_proc_msg *pm)
|
||||
if (bus->no_explore != 0)
|
||||
return;
|
||||
|
||||
if (udev && udev->hub) {
|
||||
if (udev != NULL) {
|
||||
USB_BUS_UNLOCK(bus);
|
||||
uhub_explore_handle_re_enumerate(udev);
|
||||
USB_BUS_LOCK(bus);
|
||||
}
|
||||
|
||||
if (udev != NULL && udev->hub != NULL) {
|
||||
|
||||
if (bus->do_probe) {
|
||||
bus->do_probe = 0;
|
||||
@ -411,7 +439,7 @@ usb_bus_detach(struct usb_proc_msg *pm)
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bus_suspend
|
||||
*
|
||||
* This function is used to suspend the USB contoller.
|
||||
* This function is used to suspend the USB controller.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_bus_suspend(struct usb_proc_msg *pm)
|
||||
@ -421,6 +449,8 @@ usb_bus_suspend(struct usb_proc_msg *pm)
|
||||
usb_error_t err;
|
||||
uint8_t do_unlock;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
bus = ((struct usb_bus_msg *)pm)->bus;
|
||||
udev = bus->devices[USB_ROOT_HUB_ADDR];
|
||||
|
||||
@ -466,7 +496,7 @@ usb_bus_suspend(struct usb_proc_msg *pm)
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bus_resume
|
||||
*
|
||||
* This function is used to resume the USB contoller.
|
||||
* This function is used to resume the USB controller.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_bus_resume(struct usb_proc_msg *pm)
|
||||
@ -476,6 +506,8 @@ usb_bus_resume(struct usb_proc_msg *pm)
|
||||
usb_error_t err;
|
||||
uint8_t do_unlock;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
bus = ((struct usb_bus_msg *)pm)->bus;
|
||||
udev = bus->devices[USB_ROOT_HUB_ADDR];
|
||||
|
||||
@ -524,10 +556,32 @@ usb_bus_resume(struct usb_proc_msg *pm)
|
||||
USB_BUS_LOCK(bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bus_reset
|
||||
*
|
||||
* This function is used to reset the USB controller.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_bus_reset(struct usb_proc_msg *pm)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
bus = ((struct usb_bus_msg *)pm)->bus;
|
||||
|
||||
if (bus->bdev == NULL || bus->no_explore != 0)
|
||||
return;
|
||||
|
||||
/* a suspend and resume will reset the USB controller */
|
||||
usb_bus_suspend(pm);
|
||||
usb_bus_resume(pm);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bus_shutdown
|
||||
*
|
||||
* This function is used to shutdown the USB contoller.
|
||||
* This function is used to shutdown the USB controller.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_bus_shutdown(struct usb_proc_msg *pm)
|
||||
@ -740,6 +794,11 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
|
||||
bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
|
||||
bus->resume_msg[1].bus = bus;
|
||||
|
||||
bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset;
|
||||
bus->reset_msg[0].bus = bus;
|
||||
bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset;
|
||||
bus->reset_msg[1].bus = bus;
|
||||
|
||||
bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
|
||||
bus->shutdown_msg[0].bus = bus;
|
||||
bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
|
||||
|
@ -166,7 +166,8 @@
|
||||
#define XHCI_IMOD_IVAL_SET(x) (((x) & 0xFFFF) << 0) /* 250ns unit */
|
||||
#define XHCI_IMOD_ICNT_GET(x) (((x) >> 16) & 0xFFFF) /* 250ns unit */
|
||||
#define XHCI_IMOD_ICNT_SET(x) (((x) & 0xFFFF) << 16) /* 250ns unit */
|
||||
#define XHCI_IMOD_DEFAULT 0x000003E8U /* 8000 IRQ/second */
|
||||
#define XHCI_IMOD_DEFAULT 0x000001F4U /* 8000 IRQs/second */
|
||||
#define XHCI_IMOD_DEFAULT_LP 0x000003F8U /* 4000 IRQs/second - LynxPoint */
|
||||
#define XHCI_ERSTSZ(n) (0x0028 + (0x20 * (n))) /* XHCI event ring segment table size */
|
||||
#define XHCI_ERSTS_GET(x) ((x) & 0xFFFF)
|
||||
#define XHCI_ERSTS_SET(x) ((x) & 0xFFFF)
|
||||
|
@ -95,6 +95,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC),
|
||||
USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
|
||||
USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
|
||||
USB_QUIRK(REALTEK, RTL8196EU, 0x0000, 0xffff, UQ_CFG_INDEX_1),
|
||||
USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
|
||||
USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
|
||||
/* Quirks for printer devices */
|
||||
@ -114,6 +115,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(ITUNERNET, USBLCD2X20, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
|
||||
@ -165,6 +167,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(ASAHIOPTICAL, OPTIO330, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(ATP, EUSB, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(BELKIN, USB2SCSI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI),
|
||||
USB_QUIRK(CASIO, QV_DIGICAM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
|
||||
@ -235,6 +238,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(KINGSTON, HYPERX3_0, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(KYOCERA, FINECAM_L3, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(KYOCERA, FINECAM_S3X, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
|
||||
@ -287,6 +291,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
|
||||
USB_QUIRK(NETCHIP, CLIK_40, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_ATAPI,
|
||||
UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(NETCHIP, POCKETBOOK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(NIKON, D300, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI),
|
||||
USB_QUIRK(OLYMPUS, C1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
@ -333,6 +338,9 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(SANDISK, SDDR12, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
|
||||
UQ_MSC_NO_GETMAXLUN),
|
||||
USB_QUIRK(SANDISK, SDCZ2_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(SANDISK, SDCZ2_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
|
||||
USB_QUIRK(SANDISK, SDCZ4_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
@ -398,6 +406,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW),
|
||||
USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(SUPERTOP, FLASHDRIVE, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(TAUGA, CAMERAMATE, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
|
||||
USB_QUIRK(TEAC, FD05PUB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
|
||||
UQ_MSC_FORCE_PROTO_UFI),
|
||||
@ -427,6 +437,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY_EVPD,
|
||||
UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WESTERN, MYPASSWORD, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ),
|
||||
USB_QUIRK(WESTERN, MYPASSPORT, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
|
||||
USB_QUIRK(WINMAXGROUP, FLASH64MC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
|
||||
USB_QUIRK(YANO, FW800HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
|
||||
|
@ -1326,10 +1326,12 @@ umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
}
|
||||
sc->cbw.bCDBLength = sc->sc_transfer.cmd_len;
|
||||
|
||||
/* copy SCSI command data */
|
||||
memcpy(sc->cbw.CBWCDB, sc->sc_transfer.cmd_data,
|
||||
sc->sc_transfer.cmd_len);
|
||||
|
||||
memset(sc->sc_transfer.cmd_data +
|
||||
/* clear remaining command area */
|
||||
memset(sc->cbw.CBWCDB +
|
||||
sc->sc_transfer.cmd_len, 0,
|
||||
sizeof(sc->cbw.CBWCDB) -
|
||||
sc->sc_transfer.cmd_len);
|
||||
|
@ -493,8 +493,11 @@ typedef struct usb_interface_assoc_descriptor usb_interface_assoc_descriptor_t;
|
||||
#define UICLASS_WIRELESS 0xe0
|
||||
#define UISUBCLASS_RF 0x01
|
||||
#define UIPROTO_BLUETOOTH 0x01
|
||||
#define UIPROTO_RNDIS 0x03
|
||||
|
||||
#define UICLASS_IAD 0xEF /* Interface Association Descriptor */
|
||||
#define UISUBCLASS_SYNC 0x01
|
||||
#define UIPROTO_ACTIVESYNC 0x01
|
||||
|
||||
#define UICLASS_APPL_SPEC 0xfe
|
||||
#define UISUBCLASS_FIRMWARE_DOWNLOAD 1
|
||||
|
@ -73,6 +73,7 @@ struct usb_bus {
|
||||
struct usb_bus_msg attach_msg[2];
|
||||
struct usb_bus_msg suspend_msg[2];
|
||||
struct usb_bus_msg resume_msg[2];
|
||||
struct usb_bus_msg reset_msg[2];
|
||||
struct usb_bus_msg shutdown_msg[2];
|
||||
/*
|
||||
* This mutex protects the USB hardware:
|
||||
|
@ -213,9 +213,7 @@ usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset,
|
||||
struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
|
||||
{
|
||||
struct usb_m_copy_in_arg arg = {cache, dst_offset};
|
||||
int error;
|
||||
|
||||
error = m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
|
||||
(void) m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -360,8 +358,7 @@ usb_dma_tag_create(struct usb_dma_tag *udt,
|
||||
if (bus_dma_tag_create
|
||||
( /* parent */ udt->tag_parent->tag,
|
||||
/* alignment */ align,
|
||||
/* boundary */ (align == 1) ?
|
||||
USB_PAGE_SIZE : 0,
|
||||
/* boundary */ 0,
|
||||
/* lowaddr */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
|
||||
/* highaddr */ BUS_SPACE_MAXADDR,
|
||||
/* filter */ NULL,
|
||||
@ -420,6 +417,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
|
||||
struct usb_page_cache *pc;
|
||||
struct usb_page *pg;
|
||||
usb_size_t rem;
|
||||
bus_size_t off;
|
||||
uint8_t owned;
|
||||
|
||||
pc = arg;
|
||||
@ -435,12 +433,13 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
|
||||
if (error) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
off = 0;
|
||||
pg = pc->page_start;
|
||||
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
|
||||
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
|
||||
pc->page_offset_buf = rem;
|
||||
pc->page_offset_end += rem;
|
||||
nseg--;
|
||||
#ifdef USB_DEBUG
|
||||
if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
|
||||
/*
|
||||
@ -451,11 +450,19 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
while (nseg > 0) {
|
||||
nseg--;
|
||||
segs++;
|
||||
while (pc->ismultiseg) {
|
||||
off += USB_PAGE_SIZE;
|
||||
if (off >= (segs->ds_len + rem)) {
|
||||
/* page crossing */
|
||||
nseg--;
|
||||
segs++;
|
||||
off = 0;
|
||||
rem = 0;
|
||||
if (nseg == 0)
|
||||
break;
|
||||
}
|
||||
pg++;
|
||||
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
|
||||
pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -186,6 +186,7 @@ void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
|
||||
uint8_t usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, usb_bus_mem_cb_t *cb);
|
||||
void usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
|
||||
uint16_t usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr);
|
||||
void usb_bus_reset_async_locked(struct usb_bus *bus);
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
uint8_t usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time);
|
||||
#endif
|
||||
|
@ -113,6 +113,8 @@ struct usb_xfer_flags_int {
|
||||
uint8_t can_cancel_immed:1; /* set if USB transfer can be
|
||||
* cancelled immediately */
|
||||
uint8_t doing_callback:1; /* set if executing the callback */
|
||||
uint8_t maxp_was_clamped:1; /* set if the max packet size
|
||||
* was outside its allowed range */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -107,7 +107,7 @@ static void usb_dev_uninit(void *);
|
||||
static int usb_fifo_uiomove(struct usb_fifo *, void *, int,
|
||||
struct uio *);
|
||||
static void usb_fifo_check_methods(struct usb_fifo_methods *);
|
||||
static struct usb_fifo *usb_fifo_alloc(void);
|
||||
static struct usb_fifo *usb_fifo_alloc(struct mtx *);
|
||||
static struct usb_endpoint *usb_dev_get_ep(struct usb_device *, uint8_t,
|
||||
uint8_t);
|
||||
static void usb_loc_fill(struct usb_fs_privdata *,
|
||||
@ -122,6 +122,7 @@ static d_ioctl_t usb_ioctl;
|
||||
static d_read_t usb_read;
|
||||
static d_write_t usb_write;
|
||||
static d_poll_t usb_poll;
|
||||
static d_kqfilter_t usb_kqfilter;
|
||||
|
||||
static d_ioctl_t usb_static_ioctl;
|
||||
|
||||
@ -139,7 +140,8 @@ struct cdevsw usb_devsw = {
|
||||
.d_flags = D_TRACKCLOSE,
|
||||
.d_read = usb_read,
|
||||
.d_write = usb_write,
|
||||
.d_poll = usb_poll
|
||||
.d_poll = usb_poll,
|
||||
.d_kqfilter = usb_kqfilter,
|
||||
};
|
||||
|
||||
static struct cdev* usb_dev = NULL;
|
||||
@ -205,12 +207,18 @@ usb_ref_device(struct usb_cdev_privdata *cpd,
|
||||
DPRINTFN(2, "no device at %u\n", cpd->dev_index);
|
||||
goto error;
|
||||
}
|
||||
if (cpd->udev->refcount == USB_DEV_REF_MAX) {
|
||||
DPRINTFN(2, "no dev ref\n");
|
||||
if (cpd->udev->state == USB_STATE_DETACHED &&
|
||||
(need_uref != 2)) {
|
||||
DPRINTFN(2, "device is detached\n");
|
||||
goto error;
|
||||
}
|
||||
if (need_uref) {
|
||||
DPRINTFN(2, "ref udev - needed\n");
|
||||
|
||||
if (cpd->udev->refcount == USB_DEV_REF_MAX) {
|
||||
DPRINTFN(2, "no dev ref\n");
|
||||
goto error;
|
||||
}
|
||||
cpd->udev->refcount++;
|
||||
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
@ -284,9 +292,8 @@ error:
|
||||
usbd_enum_unlock(cpd->udev);
|
||||
|
||||
if (crd->is_uref) {
|
||||
if (--(cpd->udev->refcount) == 0) {
|
||||
cv_signal(&cpd->udev->ref_cv);
|
||||
}
|
||||
cpd->udev->refcount--;
|
||||
cv_broadcast(&cpd->udev->ref_cv);
|
||||
}
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
DPRINTFN(2, "fail\n");
|
||||
@ -352,24 +359,25 @@ usb_unref_device(struct usb_cdev_privdata *cpd,
|
||||
crd->is_write = 0;
|
||||
}
|
||||
if (crd->is_uref) {
|
||||
if (--(cpd->udev->refcount) == 0) {
|
||||
cv_signal(&cpd->udev->ref_cv);
|
||||
}
|
||||
crd->is_uref = 0;
|
||||
cpd->udev->refcount--;
|
||||
cv_broadcast(&cpd->udev->ref_cv);
|
||||
}
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
}
|
||||
|
||||
static struct usb_fifo *
|
||||
usb_fifo_alloc(void)
|
||||
usb_fifo_alloc(struct mtx *mtx)
|
||||
{
|
||||
struct usb_fifo *f;
|
||||
|
||||
f = malloc(sizeof(*f), M_USBDEV, M_WAITOK | M_ZERO);
|
||||
if (f) {
|
||||
if (f != NULL) {
|
||||
cv_init(&f->cv_io, "FIFO-IO");
|
||||
cv_init(&f->cv_drain, "FIFO-DRAIN");
|
||||
f->priv_mtx = mtx;
|
||||
f->refcount = 1;
|
||||
knlist_init_mtx(&f->selinfo.si_note, mtx);
|
||||
}
|
||||
return (f);
|
||||
}
|
||||
@ -493,7 +501,7 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
|
||||
DPRINTFN(5, "dev_get_endpoint returned NULL\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
f = usb_fifo_alloc();
|
||||
f = usb_fifo_alloc(&udev->device_mtx);
|
||||
if (f == NULL) {
|
||||
DPRINTFN(5, "could not alloc tx fifo\n");
|
||||
return (ENOMEM);
|
||||
@ -501,7 +509,6 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
|
||||
/* update some fields */
|
||||
f->fifo_index = n + USB_FIFO_TX;
|
||||
f->dev_ep_index = e;
|
||||
f->priv_mtx = &udev->device_mtx;
|
||||
f->priv_sc0 = ep;
|
||||
f->methods = &usb_ugen_methods;
|
||||
f->iface_index = ep->iface_index;
|
||||
@ -520,7 +527,7 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
|
||||
DPRINTFN(5, "dev_get_endpoint returned NULL\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
f = usb_fifo_alloc();
|
||||
f = usb_fifo_alloc(&udev->device_mtx);
|
||||
if (f == NULL) {
|
||||
DPRINTFN(5, "could not alloc rx fifo\n");
|
||||
return (ENOMEM);
|
||||
@ -528,7 +535,6 @@ usb_fifo_create(struct usb_cdev_privdata *cpd,
|
||||
/* update some fields */
|
||||
f->fifo_index = n + USB_FIFO_RX;
|
||||
f->dev_ep_index = e;
|
||||
f->priv_mtx = &udev->device_mtx;
|
||||
f->priv_sc0 = ep;
|
||||
f->methods = &usb_ugen_methods;
|
||||
f->iface_index = ep->iface_index;
|
||||
@ -595,6 +601,13 @@ usb_fifo_free(struct usb_fifo *f)
|
||||
mtx_unlock(f->priv_mtx);
|
||||
mtx_lock(&usb_ref_lock);
|
||||
|
||||
/*
|
||||
* Check if the "f->refcount" variable reached zero
|
||||
* during the unlocked time before entering wait:
|
||||
*/
|
||||
if (f->refcount == 0)
|
||||
break;
|
||||
|
||||
/* wait for sync */
|
||||
cv_wait(&f->cv_drain, &usb_ref_lock);
|
||||
}
|
||||
@ -606,6 +619,10 @@ usb_fifo_free(struct usb_fifo *f)
|
||||
cv_destroy(&f->cv_io);
|
||||
cv_destroy(&f->cv_drain);
|
||||
|
||||
knlist_clear(&f->selinfo.si_note, 0);
|
||||
seldrain(&f->selinfo);
|
||||
knlist_destroy(&f->selinfo.si_note);
|
||||
|
||||
free(f, M_USBDEV);
|
||||
}
|
||||
|
||||
@ -760,7 +777,12 @@ usb_fifo_close(struct usb_fifo *f, int fflags)
|
||||
mtx_lock(f->priv_mtx);
|
||||
|
||||
/* clear current cdev private data pointer */
|
||||
mtx_lock(&usb_ref_lock);
|
||||
f->curr_cpd = NULL;
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
|
||||
/* check if we are watched by kevent */
|
||||
KNOTE_LOCKED(&f->selinfo.si_note, 0);
|
||||
|
||||
/* check if we are selected */
|
||||
if (f->flag_isselect) {
|
||||
@ -913,23 +935,12 @@ usb_close(void *arg)
|
||||
|
||||
DPRINTFN(2, "cpd=%p\n", cpd);
|
||||
|
||||
err = usb_ref_device(cpd, &refs, 0);
|
||||
if (err)
|
||||
err = usb_ref_device(cpd, &refs,
|
||||
2 /* uref and allow detached state */);
|
||||
if (err) {
|
||||
DPRINTFN(2, "Cannot grab USB reference when "
|
||||
"closing USB file handle\n");
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* If this function is not called directly from the root HUB
|
||||
* thread, there is usually a need to lock the enumeration
|
||||
* lock. Check this.
|
||||
*/
|
||||
if (!usbd_enum_is_locked(cpd->udev)) {
|
||||
|
||||
DPRINTFN(2, "Locking enumeration\n");
|
||||
|
||||
/* reference device */
|
||||
err = usb_usb_ref_device(cpd, &refs);
|
||||
if (err)
|
||||
goto done;
|
||||
}
|
||||
if (cpd->fflags & FREAD) {
|
||||
usb_fifo_close(refs.rxfifo, cpd->fflags);
|
||||
@ -1097,15 +1108,20 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
|
||||
|
||||
/* Wait for re-enumeration, if any */
|
||||
|
||||
while (f->udev->re_enumerate_wait != 0) {
|
||||
while (f->udev->re_enumerate_wait != USB_RE_ENUM_DONE) {
|
||||
|
||||
usb_unref_device(cpd, &refs);
|
||||
|
||||
usb_pause_mtx(NULL, hz / 128);
|
||||
|
||||
if (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
|
||||
err = ENXIO;
|
||||
goto done;
|
||||
while (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
|
||||
if (usb_ref_device(cpd, &refs, 0)) {
|
||||
/* device no longer exits */
|
||||
err = ENXIO;
|
||||
goto done;
|
||||
}
|
||||
usb_unref_device(cpd, &refs);
|
||||
usb_pause_mtx(NULL, hz / 128);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1114,6 +1130,162 @@ done:
|
||||
return (err);
|
||||
}
|
||||
|
||||
static void
|
||||
usb_filter_detach(struct knote *kn)
|
||||
{
|
||||
struct usb_fifo *f = kn->kn_hook;
|
||||
knlist_remove(&f->selinfo.si_note, kn, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
usb_filter_write(struct knote *kn, long hint)
|
||||
{
|
||||
struct usb_cdev_privdata* cpd;
|
||||
struct usb_fifo *f;
|
||||
struct usb_mbuf *m;
|
||||
|
||||
DPRINTFN(2, "\n");
|
||||
|
||||
f = kn->kn_hook;
|
||||
|
||||
mtx_assert(f->priv_mtx, MA_OWNED);
|
||||
|
||||
cpd = f->curr_cpd;
|
||||
if (cpd == NULL) {
|
||||
m = (void *)1;
|
||||
} else if (f->fs_ep_max == 0) {
|
||||
if (f->flag_iserror) {
|
||||
/* we got an error */
|
||||
m = (void *)1;
|
||||
} else {
|
||||
if (f->queue_data == NULL) {
|
||||
/*
|
||||
* start write transfer, if not
|
||||
* already started
|
||||
*/
|
||||
(f->methods->f_start_write) (f);
|
||||
}
|
||||
/* check if any packets are available */
|
||||
USB_IF_POLL(&f->free_q, m);
|
||||
}
|
||||
} else {
|
||||
if (f->flag_iscomplete) {
|
||||
m = (void *)1;
|
||||
} else {
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
return (m ? 1 : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
usb_filter_read(struct knote *kn, long hint)
|
||||
{
|
||||
struct usb_cdev_privdata* cpd;
|
||||
struct usb_fifo *f;
|
||||
struct usb_mbuf *m;
|
||||
|
||||
DPRINTFN(2, "\n");
|
||||
|
||||
f = kn->kn_hook;
|
||||
|
||||
mtx_assert(f->priv_mtx, MA_OWNED);
|
||||
|
||||
cpd = f->curr_cpd;
|
||||
if (cpd == NULL) {
|
||||
m = (void *)1;
|
||||
} else if (f->fs_ep_max == 0) {
|
||||
if (f->flag_iserror) {
|
||||
/* we have an error */
|
||||
m = (void *)1;
|
||||
} else {
|
||||
if (f->queue_data == NULL) {
|
||||
/*
|
||||
* start read transfer, if not
|
||||
* already started
|
||||
*/
|
||||
(f->methods->f_start_read) (f);
|
||||
}
|
||||
/* check if any packets are available */
|
||||
USB_IF_POLL(&f->used_q, m);
|
||||
|
||||
/* start reading data, if any */
|
||||
if (m == NULL)
|
||||
(f->methods->f_start_read) (f);
|
||||
}
|
||||
} else {
|
||||
if (f->flag_iscomplete) {
|
||||
m = (void *)1;
|
||||
} else {
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
return (m ? 1 : 0);
|
||||
}
|
||||
|
||||
static struct filterops usb_filtops_write = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = usb_filter_detach,
|
||||
.f_event = usb_filter_write,
|
||||
};
|
||||
|
||||
static struct filterops usb_filtops_read = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = usb_filter_detach,
|
||||
.f_event = usb_filter_read,
|
||||
};
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
usb_kqfilter(struct cdev* dev, struct knote *kn)
|
||||
{
|
||||
struct usb_cdev_refdata refs;
|
||||
struct usb_cdev_privdata* cpd;
|
||||
struct usb_fifo *f;
|
||||
int fflags;
|
||||
int err = EINVAL;
|
||||
|
||||
DPRINTFN(2, "\n");
|
||||
|
||||
if (devfs_get_cdevpriv((void **)&cpd) != 0 ||
|
||||
usb_ref_device(cpd, &refs, 0) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
fflags = cpd->fflags;
|
||||
|
||||
/* Figure out who needs service */
|
||||
switch (kn->kn_filter) {
|
||||
case EVFILT_WRITE:
|
||||
if (fflags & FWRITE) {
|
||||
f = refs.txfifo;
|
||||
kn->kn_fop = &usb_filtops_write;
|
||||
err = 0;
|
||||
}
|
||||
break;
|
||||
case EVFILT_READ:
|
||||
if (fflags & FREAD) {
|
||||
f = refs.rxfifo;
|
||||
kn->kn_fop = &usb_filtops_read;
|
||||
err = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
kn->kn_hook = f;
|
||||
mtx_lock(f->priv_mtx);
|
||||
knlist_add(&f->selinfo.si_note, kn, 1);
|
||||
mtx_unlock(f->priv_mtx);
|
||||
}
|
||||
|
||||
usb_unref_device(cpd, &refs);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
usb_poll(struct cdev* dev, int events, struct thread* td)
|
||||
@ -1181,7 +1353,7 @@ usb_poll(struct cdev* dev, int events, struct thread* td)
|
||||
|
||||
if (!refs.is_usbfs) {
|
||||
if (f->flag_iserror) {
|
||||
/* we have and error */
|
||||
/* we have an error */
|
||||
m = (void *)1;
|
||||
} else {
|
||||
if (f->queue_data == NULL) {
|
||||
@ -1578,6 +1750,8 @@ usb_fifo_wakeup(struct usb_fifo *f)
|
||||
{
|
||||
usb_fifo_signal(f);
|
||||
|
||||
KNOTE_LOCKED(&f->selinfo.si_note, 0);
|
||||
|
||||
if (f->flag_isselect) {
|
||||
selwakeup(&f->selinfo);
|
||||
f->flag_isselect = 0;
|
||||
@ -1693,8 +1867,8 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
|
||||
break;
|
||||
}
|
||||
|
||||
f_tx = usb_fifo_alloc();
|
||||
f_rx = usb_fifo_alloc();
|
||||
f_tx = usb_fifo_alloc(priv_mtx);
|
||||
f_rx = usb_fifo_alloc(priv_mtx);
|
||||
|
||||
if ((f_tx == NULL) || (f_rx == NULL)) {
|
||||
usb_fifo_free(f_tx);
|
||||
@ -1705,7 +1879,6 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
|
||||
|
||||
f_tx->fifo_index = n + USB_FIFO_TX;
|
||||
f_tx->dev_ep_index = -1;
|
||||
f_tx->priv_mtx = priv_mtx;
|
||||
f_tx->priv_sc0 = priv_sc;
|
||||
f_tx->methods = pm;
|
||||
f_tx->iface_index = iface_index;
|
||||
@ -1713,7 +1886,6 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
|
||||
|
||||
f_rx->fifo_index = n + USB_FIFO_RX;
|
||||
f_rx->dev_ep_index = -1;
|
||||
f_rx->priv_mtx = priv_mtx;
|
||||
f_rx->priv_sc0 = priv_sc;
|
||||
f_rx->methods = pm;
|
||||
f_rx->iface_index = iface_index;
|
||||
|
@ -96,7 +96,7 @@ static void usb_init_attach_arg(struct usb_device *,
|
||||
struct usb_attach_arg *);
|
||||
static void usb_suspend_resume_sub(struct usb_device *, device_t,
|
||||
uint8_t);
|
||||
static void usbd_clear_stall_proc(struct usb_proc_msg *_pm);
|
||||
static usb_proc_callback_t usbd_clear_stall_proc;
|
||||
static usb_error_t usb_config_parse(struct usb_device *, uint8_t, uint8_t);
|
||||
static void usbd_set_device_strings(struct usb_device *);
|
||||
#if USB_HAVE_DEVCTL
|
||||
@ -436,6 +436,65 @@ usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_wait_pending_ref_locked
|
||||
*
|
||||
* This function will wait for any USB references to go away before
|
||||
* returning and disable further USB device refcounting on the
|
||||
* specified USB device. This function is used when detaching a USB
|
||||
* device.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_wait_pending_ref_locked(struct usb_device *udev)
|
||||
{
|
||||
#if USB_HAVE_UGEN
|
||||
const uint16_t refcount =
|
||||
usb_proc_is_called_from(
|
||||
&udev->bus->explore_proc) ? 1 : 2;
|
||||
|
||||
DPRINTF("Refcount = %d\n", (int)refcount);
|
||||
|
||||
while (1) {
|
||||
/* wait for any pending references to go away */
|
||||
mtx_lock(&usb_ref_lock);
|
||||
if (udev->refcount == refcount) {
|
||||
/* prevent further refs being taken */
|
||||
udev->refcount = USB_DEV_REF_MAX;
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
break;
|
||||
}
|
||||
usbd_enum_unlock(udev);
|
||||
cv_wait(&udev->ref_cv, &usb_ref_lock);
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
(void) usbd_enum_lock(udev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_ref_restore_locked
|
||||
*
|
||||
* This function will restore the reference count value after a call
|
||||
* to "usb_wait_pending_ref_locked()".
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb_ref_restore_locked(struct usb_device *udev)
|
||||
{
|
||||
#if USB_HAVE_UGEN
|
||||
const uint16_t refcount =
|
||||
usb_proc_is_called_from(
|
||||
&udev->bus->explore_proc) ? 1 : 2;
|
||||
|
||||
DPRINTF("Refcount = %d\n", (int)refcount);
|
||||
|
||||
/* restore reference count and wakeup waiters, if any */
|
||||
mtx_lock(&usb_ref_lock);
|
||||
udev->refcount = refcount;
|
||||
cv_broadcast(&udev->ref_cv);
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_unconfigure
|
||||
*
|
||||
@ -1097,6 +1156,9 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index,
|
||||
|
||||
sx_assert(&udev->enum_sx, SA_LOCKED);
|
||||
|
||||
/* wait for pending refs to go away */
|
||||
usb_wait_pending_ref_locked(udev);
|
||||
|
||||
/*
|
||||
* First detach the child to give the child's detach routine a
|
||||
* chance to detach the sub-devices in the correct order.
|
||||
@ -1123,6 +1185,8 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index,
|
||||
usb_detach_device_sub(udev, &iface->subdev,
|
||||
&iface->pnpinfo, flag);
|
||||
}
|
||||
|
||||
usb_ref_restore_locked(udev);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -1450,7 +1514,7 @@ usb_suspend_resume(struct usb_device *udev, uint8_t do_suspend)
|
||||
static void
|
||||
usbd_clear_stall_proc(struct usb_proc_msg *_pm)
|
||||
{
|
||||
struct usb_clear_stall_msg *pm = (void *)_pm;
|
||||
struct usb_udev_msg *pm = (void *)_pm;
|
||||
struct usb_device *udev = pm->udev;
|
||||
|
||||
/* Change lock */
|
||||
@ -1679,10 +1743,14 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
|
||||
err = usbd_setup_device_desc(udev, NULL);
|
||||
|
||||
if (err != 0) {
|
||||
/* XXX try to re-enumerate the device */
|
||||
/* try to enumerate two more times */
|
||||
err = usbd_req_re_enumerate(udev, NULL);
|
||||
if (err)
|
||||
goto done;
|
||||
if (err != 0) {
|
||||
err = usbd_req_re_enumerate(udev, NULL);
|
||||
if (err != 0) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2038,6 +2106,8 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
|
||||
DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no);
|
||||
|
||||
bus = udev->bus;
|
||||
|
||||
/* set DETACHED state to prevent any further references */
|
||||
usb_set_device_state(udev, USB_STATE_DETACHED);
|
||||
|
||||
#if USB_HAVE_DEVCTL
|
||||
@ -2053,23 +2123,6 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
|
||||
usb_free_symlink(udev->ugen_symlink);
|
||||
udev->ugen_symlink = NULL;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Unregister our device first which will prevent any further
|
||||
* references:
|
||||
*/
|
||||
usb_bus_port_set_device(bus, udev->parent_hub ?
|
||||
udev->parent_hub->hub->ports + udev->port_index : NULL,
|
||||
NULL, USB_ROOT_HUB_ADDR);
|
||||
|
||||
#if USB_HAVE_UGEN
|
||||
/* wait for all pending references to go away: */
|
||||
mtx_lock(&usb_ref_lock);
|
||||
udev->refcount--;
|
||||
while (udev->refcount != 0) {
|
||||
cv_wait(&udev->ref_cv, &usb_ref_lock);
|
||||
}
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
|
||||
usb_destroy_dev(udev->ctrl_dev);
|
||||
#endif
|
||||
@ -2082,6 +2135,11 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
|
||||
/* the following will get the device unconfigured in software */
|
||||
usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_EP0);
|
||||
|
||||
/* final device unregister after all character devices are closed */
|
||||
usb_bus_port_set_device(bus, udev->parent_hub ?
|
||||
udev->parent_hub->hub->ports + udev->port_index : NULL,
|
||||
NULL, USB_ROOT_HUB_ADDR);
|
||||
|
||||
/* unsetup any leftover default USB transfers */
|
||||
usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
|
||||
|
||||
@ -2582,8 +2640,14 @@ usb_fifo_free_wrap(struct usb_device *udev,
|
||||
/* no need to free this FIFO */
|
||||
continue;
|
||||
}
|
||||
/* wait for pending refs to go away */
|
||||
usb_wait_pending_ref_locked(udev);
|
||||
|
||||
/* free this FIFO */
|
||||
usb_fifo_free(f);
|
||||
|
||||
/* restore refcount */
|
||||
usb_ref_restore_locked(udev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2615,8 +2679,14 @@ usb_set_device_state(struct usb_device *udev, enum usb_dev_state state)
|
||||
|
||||
DPRINTF("udev %p state %s -> %s\n", udev,
|
||||
usb_statestr(udev->state), usb_statestr(state));
|
||||
udev->state = state;
|
||||
|
||||
#if USB_HAVE_UGEN
|
||||
mtx_lock(&usb_ref_lock);
|
||||
#endif
|
||||
udev->state = state;
|
||||
#if USB_HAVE_UGEN
|
||||
mtx_unlock(&usb_ref_lock);
|
||||
#endif
|
||||
if (udev->bus->methods->device_state_change != NULL)
|
||||
(udev->bus->methods->device_state_change) (udev);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ struct usb_symlink; /* UGEN */
|
||||
#define USB_UNCFG_FLAG_NONE 0x00
|
||||
#define USB_UNCFG_FLAG_FREE_EP0 0x02 /* endpoint zero is freed */
|
||||
|
||||
struct usb_clear_stall_msg {
|
||||
struct usb_udev_msg {
|
||||
struct usb_proc_msg hdr;
|
||||
struct usb_device *udev;
|
||||
};
|
||||
@ -179,8 +179,8 @@ union usb_device_scratch {
|
||||
* these structures for every USB device.
|
||||
*/
|
||||
struct usb_device {
|
||||
struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall
|
||||
* messages */
|
||||
/* generic clear stall message */
|
||||
struct usb_udev_msg cs_msg[2];
|
||||
struct sx enum_sx;
|
||||
struct sx sr_sx;
|
||||
struct mtx device_mtx;
|
||||
@ -220,6 +220,7 @@ struct usb_device {
|
||||
uint8_t address; /* device addess */
|
||||
uint8_t device_index; /* device index in "bus->devices" */
|
||||
uint8_t controller_slot_id; /* controller specific value */
|
||||
uint8_t next_config_index; /* used by USB_RE_ENUM_SET_CONFIG */
|
||||
uint8_t curr_config_index; /* current configuration index */
|
||||
uint8_t curr_config_no; /* current configuration number */
|
||||
uint8_t depth; /* distance from root HUB */
|
||||
@ -230,6 +231,10 @@ struct usb_device {
|
||||
uint8_t driver_added_refcount; /* our driver added generation count */
|
||||
uint8_t power_mode; /* see USB_POWER_XXX */
|
||||
uint8_t re_enumerate_wait; /* set if re-enum. is in progress */
|
||||
#define USB_RE_ENUM_DONE 0
|
||||
#define USB_RE_ENUM_START 1
|
||||
#define USB_RE_ENUM_PWR_OFF 2
|
||||
#define USB_RE_ENUM_SET_CONFIG 3
|
||||
uint8_t ifaces_max; /* number of interfaces present */
|
||||
uint8_t endpoints_max; /* number of endpoints present */
|
||||
|
||||
@ -301,4 +306,10 @@ void usbd_sr_lock(struct usb_device *);
|
||||
void usbd_sr_unlock(struct usb_device *);
|
||||
uint8_t usbd_enum_is_locked(struct usb_device *);
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
void uhub_tt_buffer_reset_async_locked(struct usb_device *, struct usb_endpoint *);
|
||||
#endif
|
||||
|
||||
uint8_t uhub_count_active_host_ports(struct usb_device *, enum usb_dev_speed);
|
||||
|
||||
#endif /* _USB_DEVICE_H_ */
|
||||
|
@ -45,6 +45,9 @@
|
||||
#define USB_HAVE_PF 1
|
||||
#endif /* __rtems__ */
|
||||
|
||||
/* define zero ticks callout value */
|
||||
#define USB_CALLOUT_ZERO_TICKS 1
|
||||
|
||||
#define USB_TD_GET_PROC(td) (td)->td_proc
|
||||
#define USB_PROC_GET_GID(td) (td)->p_pgid
|
||||
|
||||
|
@ -612,24 +612,17 @@ ugen_set_config(struct usb_fifo *f, uint8_t index)
|
||||
/* not possible in device side mode */
|
||||
return (ENOTTY);
|
||||
}
|
||||
if (f->udev->curr_config_index == index) {
|
||||
/* no change needed */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* make sure all FIFO's are gone */
|
||||
/* else there can be a deadlock */
|
||||
if (ugen_fs_uninit(f)) {
|
||||
/* ignore any errors */
|
||||
DPRINTFN(6, "no FIFOs\n");
|
||||
}
|
||||
/* change setting - will free generic FIFOs, if any */
|
||||
if (usbd_set_config_index(f->udev, index)) {
|
||||
|
||||
if (usbd_start_set_config(f->udev, index) != 0)
|
||||
return (EIO);
|
||||
}
|
||||
/* probe and attach */
|
||||
if (usb_probe_and_attach(f->udev, USB_IFACE_INDEX_ANY)) {
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -963,11 +956,6 @@ ugen_re_enumerate(struct usb_fifo *f)
|
||||
DPRINTFN(6, "device mode\n");
|
||||
return (ENOTTY);
|
||||
}
|
||||
if (udev->parent_hub == NULL) {
|
||||
/* the root HUB cannot be re-enumerated */
|
||||
DPRINTFN(6, "cannot reset root HUB\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
/* make sure all FIFO's are gone */
|
||||
/* else there can be a deadlock */
|
||||
if (ugen_fs_uninit(f)) {
|
||||
@ -1751,16 +1739,11 @@ ugen_set_power_mode(struct usb_fifo *f, int mode)
|
||||
|
||||
switch (mode) {
|
||||
case USB_POWER_MODE_OFF:
|
||||
/* get the device unconfigured */
|
||||
err = ugen_set_config(f, USB_UNCONFIG_INDEX);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Could not unconfigure "
|
||||
"device (ignored)\n");
|
||||
if (udev->flags.usb_mode == USB_MODE_HOST &&
|
||||
udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
|
||||
udev->re_enumerate_wait = USB_RE_ENUM_PWR_OFF;
|
||||
}
|
||||
|
||||
/* clear port enable */
|
||||
err = usbd_req_clear_port_feature(udev->parent_hub,
|
||||
NULL, udev->port_no, UHF_PORT_ENABLE);
|
||||
/* set power mode will wake up the explore thread */
|
||||
break;
|
||||
|
||||
case USB_POWER_MODE_ON:
|
||||
@ -1808,9 +1791,9 @@ ugen_set_power_mode(struct usb_fifo *f, int mode)
|
||||
|
||||
/* if we are powered off we need to re-enumerate first */
|
||||
if (old_mode == USB_POWER_MODE_OFF) {
|
||||
if (udev->flags.usb_mode == USB_MODE_HOST) {
|
||||
if (udev->re_enumerate_wait == 0)
|
||||
udev->re_enumerate_wait = 1;
|
||||
if (udev->flags.usb_mode == USB_MODE_HOST &&
|
||||
udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
|
||||
udev->re_enumerate_wait = USB_RE_ENUM_START;
|
||||
}
|
||||
/* set power mode will wake up the explore thread */
|
||||
}
|
||||
@ -1832,6 +1815,46 @@ ugen_get_power_mode(struct usb_fifo *f)
|
||||
return (udev->power_mode);
|
||||
}
|
||||
|
||||
static int
|
||||
ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp)
|
||||
{
|
||||
struct usb_device *udev = f->udev;
|
||||
struct usb_device *next;
|
||||
unsigned int nlevel = 0;
|
||||
|
||||
if (udev == NULL)
|
||||
goto error;
|
||||
|
||||
dpp->udp_bus = device_get_unit(udev->bus->bdev);
|
||||
dpp->udp_index = udev->device_index;
|
||||
|
||||
/* count port levels */
|
||||
next = udev;
|
||||
while (next->parent_hub != NULL) {
|
||||
nlevel++;
|
||||
next = next->parent_hub;
|
||||
}
|
||||
|
||||
/* check if too many levels */
|
||||
if (nlevel > USB_DEVICE_PORT_PATH_MAX)
|
||||
goto error;
|
||||
|
||||
/* store port index array */
|
||||
next = udev;
|
||||
while (next->parent_hub != NULL) {
|
||||
nlevel--;
|
||||
|
||||
dpp->udp_port_no[nlevel] = next->port_no;
|
||||
dpp->udp_port_level = nlevel;
|
||||
|
||||
next = next->parent_hub;
|
||||
}
|
||||
return (0); /* success */
|
||||
|
||||
error:
|
||||
return (EINVAL); /* failure */
|
||||
}
|
||||
|
||||
static int
|
||||
ugen_get_power_usage(struct usb_fifo *f)
|
||||
{
|
||||
@ -2033,6 +2056,7 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
|
||||
struct usb_device_stats *stat;
|
||||
struct usb_fs_init *pinit;
|
||||
struct usb_fs_uninit *puninit;
|
||||
struct usb_device_port_path *dpp;
|
||||
uint32_t *ptime;
|
||||
void *addr;
|
||||
int *pint;
|
||||
@ -2205,6 +2229,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
|
||||
*u.pint = ugen_get_power_mode(f);
|
||||
break;
|
||||
|
||||
case USB_GET_DEV_PORT_PATH:
|
||||
error = ugen_get_port_path(f, u.dpp);
|
||||
break;
|
||||
|
||||
case USB_GET_POWER_USAGE:
|
||||
*u.pint = ugen_get_power_usage(f);
|
||||
break;
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include <sys/priv.h>
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usb_ioctl.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
#include <dev/usb/usbdi_util.h>
|
||||
|
||||
@ -73,7 +72,13 @@
|
||||
#include <dev/usb/usb_bus.h>
|
||||
|
||||
#define UHUB_INTR_INTERVAL 250 /* ms */
|
||||
#define UHUB_N_TRANSFER 1
|
||||
enum {
|
||||
UHUB_INTR_TRANSFER,
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
UHUB_RESET_TT_TRANSFER,
|
||||
#endif
|
||||
UHUB_N_TRANSFER,
|
||||
};
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
static int uhub_debug = 0;
|
||||
@ -126,6 +131,9 @@ static bus_child_location_str_t uhub_child_location_string;
|
||||
static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
|
||||
|
||||
static usb_callback_t uhub_intr_callback;
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
static usb_callback_t uhub_reset_tt_callback;
|
||||
#endif
|
||||
|
||||
static void usb_dev_resume_peer(struct usb_device *udev);
|
||||
static void usb_dev_suspend_peer(struct usb_device *udev);
|
||||
@ -133,7 +141,7 @@ static uint8_t usb_peer_should_wakeup(struct usb_device *udev);
|
||||
|
||||
static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
|
||||
|
||||
[0] = {
|
||||
[UHUB_INTR_TRANSFER] = {
|
||||
.type = UE_INTERRUPT,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_ANY,
|
||||
@ -143,6 +151,17 @@ static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
|
||||
.callback = &uhub_intr_callback,
|
||||
.interval = UHUB_INTR_INTERVAL,
|
||||
},
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
[UHUB_RESET_TT_TRANSFER] = {
|
||||
.type = UE_CONTROL,
|
||||
.endpoint = 0x00, /* Control pipe */
|
||||
.direction = UE_DIR_ANY,
|
||||
.bufsize = sizeof(struct usb_device_request),
|
||||
.callback = &uhub_reset_tt_callback,
|
||||
.timeout = 1000, /* 1 second */
|
||||
.usb_mode = USB_MODE_HOST,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -211,6 +230,279 @@ uhub_intr_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_reset_tt_proc
|
||||
*
|
||||
* This function starts the TT reset USB request
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
static void
|
||||
uhub_reset_tt_proc(struct usb_proc_msg *_pm)
|
||||
{
|
||||
struct usb_udev_msg *pm = (void *)_pm;
|
||||
struct usb_device *udev = pm->udev;
|
||||
struct usb_hub *hub;
|
||||
struct uhub_softc *sc;
|
||||
|
||||
hub = udev->hub;
|
||||
if (hub == NULL)
|
||||
return;
|
||||
sc = hub->hubsoftc;
|
||||
if (sc == NULL)
|
||||
return;
|
||||
|
||||
/* Change lock */
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
/* Start transfer */
|
||||
usbd_transfer_start(sc->sc_xfer[UHUB_RESET_TT_TRANSFER]);
|
||||
/* Change lock */
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_tt_buffer_reset_async_locked
|
||||
*
|
||||
* This function queues a TT reset for the given USB device and endpoint.
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
void
|
||||
uhub_tt_buffer_reset_async_locked(struct usb_device *child, struct usb_endpoint *ep)
|
||||
{
|
||||
struct usb_device_request req;
|
||||
struct usb_device *udev;
|
||||
struct usb_hub *hub;
|
||||
struct usb_port *up;
|
||||
uint16_t wValue;
|
||||
uint8_t port;
|
||||
|
||||
if (child == NULL || ep == NULL)
|
||||
return;
|
||||
|
||||
udev = child->parent_hs_hub;
|
||||
port = child->hs_port_no;
|
||||
|
||||
if (udev == NULL)
|
||||
return;
|
||||
|
||||
hub = udev->hub;
|
||||
if ((hub == NULL) ||
|
||||
(udev->speed != USB_SPEED_HIGH) ||
|
||||
(child->speed != USB_SPEED_LOW &&
|
||||
child->speed != USB_SPEED_FULL) ||
|
||||
(child->flags.usb_mode != USB_MODE_HOST) ||
|
||||
(port == 0) || (ep->edesc == NULL)) {
|
||||
/* not applicable */
|
||||
return;
|
||||
}
|
||||
|
||||
USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
|
||||
|
||||
up = hub->ports + port - 1;
|
||||
|
||||
if (udev->ddesc.bDeviceClass == UDCLASS_HUB &&
|
||||
udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBSTT)
|
||||
port = 1;
|
||||
|
||||
/* if we already received a clear buffer request, reset the whole TT */
|
||||
if (up->req_reset_tt.bRequest != 0) {
|
||||
req.bmRequestType = UT_WRITE_CLASS_OTHER;
|
||||
req.bRequest = UR_RESET_TT;
|
||||
USETW(req.wValue, 0);
|
||||
req.wIndex[0] = port;
|
||||
req.wIndex[1] = 0;
|
||||
USETW(req.wLength, 0);
|
||||
} else {
|
||||
wValue = (ep->edesc->bEndpointAddress & 0xF) |
|
||||
((child->address & 0x7F) << 4) |
|
||||
((ep->edesc->bEndpointAddress & 0x80) << 8) |
|
||||
((ep->edesc->bmAttributes & 3) << 12);
|
||||
|
||||
req.bmRequestType = UT_WRITE_CLASS_OTHER;
|
||||
req.bRequest = UR_CLEAR_TT_BUFFER;
|
||||
USETW(req.wValue, wValue);
|
||||
req.wIndex[0] = port;
|
||||
req.wIndex[1] = 0;
|
||||
USETW(req.wLength, 0);
|
||||
}
|
||||
up->req_reset_tt = req;
|
||||
/* get reset transfer started */
|
||||
usb_proc_msignal(&udev->bus->non_giant_callback_proc,
|
||||
&hub->tt_msg[0], &hub->tt_msg[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
static void
|
||||
uhub_reset_tt_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct uhub_softc *sc;
|
||||
struct usb_device *udev;
|
||||
struct usb_port *up;
|
||||
uint8_t x;
|
||||
|
||||
DPRINTF("TT buffer reset\n");
|
||||
|
||||
sc = usbd_xfer_softc(xfer);
|
||||
udev = sc->sc_udev;
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
/* find first port which needs a TT reset */
|
||||
for (x = 0; x != udev->hub->nports; x++) {
|
||||
up = udev->hub->ports + x;
|
||||
|
||||
if (up->req_reset_tt.bRequest == 0)
|
||||
continue;
|
||||
|
||||
/* copy in the transfer */
|
||||
usbd_copy_in(xfer->frbuffers, 0, &up->req_reset_tt,
|
||||
sizeof(up->req_reset_tt));
|
||||
/* reset buffer */
|
||||
memset(&up->req_reset_tt, 0, sizeof(up->req_reset_tt));
|
||||
|
||||
/* set length */
|
||||
usbd_xfer_set_frame_len(xfer, 0, sizeof(up->req_reset_tt));
|
||||
xfer->nframes = 1;
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
usbd_transfer_submit(xfer);
|
||||
return;
|
||||
}
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (error == USB_ERR_CANCELLED)
|
||||
break;
|
||||
|
||||
DPRINTF("TT buffer reset failed (%s)\n", usbd_errstr(error));
|
||||
goto tr_setup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_count_active_host_ports
|
||||
*
|
||||
* This function counts the number of active ports at the given speed.
|
||||
*------------------------------------------------------------------------*/
|
||||
uint8_t
|
||||
uhub_count_active_host_ports(struct usb_device *udev, enum usb_dev_speed speed)
|
||||
{
|
||||
struct uhub_softc *sc;
|
||||
struct usb_device *child;
|
||||
struct usb_hub *hub;
|
||||
struct usb_port *up;
|
||||
uint8_t retval = 0;
|
||||
uint8_t x;
|
||||
|
||||
if (udev == NULL)
|
||||
goto done;
|
||||
hub = udev->hub;
|
||||
if (hub == NULL)
|
||||
goto done;
|
||||
sc = hub->hubsoftc;
|
||||
if (sc == NULL)
|
||||
goto done;
|
||||
|
||||
for (x = 0; x != hub->nports; x++) {
|
||||
up = hub->ports + x;
|
||||
child = usb_bus_port_get_device(udev->bus, up);
|
||||
if (child != NULL &&
|
||||
child->flags.usb_mode == USB_MODE_HOST &&
|
||||
child->speed == speed)
|
||||
retval++;
|
||||
}
|
||||
done:
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
uhub_explore_handle_re_enumerate(struct usb_device *child)
|
||||
{
|
||||
uint8_t do_unlock;
|
||||
usb_error_t err;
|
||||
|
||||
/* check if device should be re-enumerated */
|
||||
if (child->flags.usb_mode != USB_MODE_HOST)
|
||||
return;
|
||||
|
||||
do_unlock = usbd_enum_lock(child);
|
||||
switch (child->re_enumerate_wait) {
|
||||
case USB_RE_ENUM_START:
|
||||
err = usbd_set_config_index(child,
|
||||
USB_UNCONFIG_INDEX);
|
||||
if (err != 0) {
|
||||
DPRINTF("Unconfigure failed: %s: Ignored.\n",
|
||||
usbd_errstr(err));
|
||||
}
|
||||
if (child->parent_hub == NULL) {
|
||||
/* the root HUB cannot be re-enumerated */
|
||||
DPRINTFN(6, "cannot reset root HUB\n");
|
||||
err = 0;
|
||||
} else {
|
||||
err = usbd_req_re_enumerate(child, NULL);
|
||||
}
|
||||
if (err == 0)
|
||||
err = usbd_set_config_index(child, 0);
|
||||
if (err == 0) {
|
||||
err = usb_probe_and_attach(child,
|
||||
USB_IFACE_INDEX_ANY);
|
||||
}
|
||||
child->re_enumerate_wait = USB_RE_ENUM_DONE;
|
||||
break;
|
||||
|
||||
case USB_RE_ENUM_PWR_OFF:
|
||||
/* get the device unconfigured */
|
||||
err = usbd_set_config_index(child,
|
||||
USB_UNCONFIG_INDEX);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Could not unconfigure "
|
||||
"device (ignored)\n");
|
||||
}
|
||||
if (child->parent_hub == NULL) {
|
||||
/* the root HUB cannot be re-enumerated */
|
||||
DPRINTFN(6, "cannot set port feature\n");
|
||||
err = 0;
|
||||
} else {
|
||||
/* clear port enable */
|
||||
err = usbd_req_clear_port_feature(child->parent_hub,
|
||||
NULL, child->port_no, UHF_PORT_ENABLE);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Could not disable port "
|
||||
"(ignored)\n");
|
||||
}
|
||||
}
|
||||
child->re_enumerate_wait = USB_RE_ENUM_DONE;
|
||||
break;
|
||||
|
||||
case USB_RE_ENUM_SET_CONFIG:
|
||||
err = usbd_set_config_index(child,
|
||||
child->next_config_index);
|
||||
if (err != 0) {
|
||||
DPRINTF("Configure failed: %s: Ignored.\n",
|
||||
usbd_errstr(err));
|
||||
} else {
|
||||
err = usb_probe_and_attach(child,
|
||||
USB_IFACE_INDEX_ANY);
|
||||
}
|
||||
child->re_enumerate_wait = USB_RE_ENUM_DONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
child->re_enumerate_wait = USB_RE_ENUM_DONE;
|
||||
break;
|
||||
}
|
||||
if (do_unlock)
|
||||
usbd_enum_unlock(child);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_explore_sub - subroutine
|
||||
*
|
||||
@ -239,33 +531,7 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check if device should be re-enumerated */
|
||||
|
||||
if (child->flags.usb_mode == USB_MODE_HOST) {
|
||||
uint8_t do_unlock;
|
||||
|
||||
do_unlock = usbd_enum_lock(child);
|
||||
if (child->re_enumerate_wait) {
|
||||
err = usbd_set_config_index(child,
|
||||
USB_UNCONFIG_INDEX);
|
||||
if (err != 0) {
|
||||
DPRINTF("Unconfigure failed: "
|
||||
"%s: Ignored.\n",
|
||||
usbd_errstr(err));
|
||||
}
|
||||
err = usbd_req_re_enumerate(child, NULL);
|
||||
if (err == 0)
|
||||
err = usbd_set_config_index(child, 0);
|
||||
if (err == 0) {
|
||||
err = usb_probe_and_attach(child,
|
||||
USB_IFACE_INDEX_ANY);
|
||||
}
|
||||
child->re_enumerate_wait = 0;
|
||||
err = 0;
|
||||
}
|
||||
if (do_unlock)
|
||||
usbd_enum_unlock(child);
|
||||
}
|
||||
uhub_explore_handle_re_enumerate(child);
|
||||
|
||||
/* check if probe and attach should be done */
|
||||
|
||||
@ -522,7 +788,10 @@ repeat:
|
||||
*
|
||||
* NOTE: This part is currently FreeBSD specific.
|
||||
*/
|
||||
if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
|
||||
if (udev->parent_hub != NULL) {
|
||||
/* inherit mode from the parent HUB */
|
||||
mode = udev->parent_hub->flags.usb_mode;
|
||||
} else if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
|
||||
mode = USB_MODE_DEVICE;
|
||||
else
|
||||
mode = USB_MODE_HOST;
|
||||
@ -1079,7 +1348,12 @@ uhub_attach(device_t dev)
|
||||
hub->explore = &uhub_explore;
|
||||
hub->nports = nports;
|
||||
hub->hubudev = udev;
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
hub->tt_msg[0].hdr.pm_callback = &uhub_reset_tt_proc;
|
||||
hub->tt_msg[0].udev = udev;
|
||||
hub->tt_msg[1].hdr.pm_callback = &uhub_reset_tt_proc;
|
||||
hub->tt_msg[1].udev = udev;
|
||||
#endif
|
||||
/* if self powered hub, give ports maximum current */
|
||||
if (udev->flags.self_powered) {
|
||||
hub->portpower = USB_MAX_POWER;
|
||||
@ -1181,11 +1455,9 @@ uhub_attach(device_t dev)
|
||||
|
||||
/* Start the interrupt endpoint, if any */
|
||||
|
||||
if (sc->sc_xfer[0] != NULL) {
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
usbd_transfer_start(sc->sc_xfer[0]);
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
}
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
usbd_transfer_start(sc->sc_xfer[UHUB_INTR_TRANSFER]);
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
|
||||
/* Enable automatic power save on all USB HUBs */
|
||||
|
||||
@ -1215,6 +1487,7 @@ uhub_detach(device_t dev)
|
||||
{
|
||||
struct uhub_softc *sc = device_get_softc(dev);
|
||||
struct usb_hub *hub = sc->sc_udev->hub;
|
||||
struct usb_bus *bus = sc->sc_udev->bus;
|
||||
struct usb_device *child;
|
||||
uint8_t x;
|
||||
|
||||
@ -1227,7 +1500,7 @@ uhub_detach(device_t dev)
|
||||
/* Detach all ports */
|
||||
for (x = 0; x != hub->nports; x++) {
|
||||
|
||||
child = usb_bus_port_get_device(sc->sc_udev->bus, hub->ports + x);
|
||||
child = usb_bus_port_get_device(bus, hub->ports + x);
|
||||
|
||||
if (child == NULL) {
|
||||
continue;
|
||||
@ -1239,6 +1512,13 @@ uhub_detach(device_t dev)
|
||||
usb_free_device(child, 0);
|
||||
}
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
/* Make sure our TT messages are not queued anywhere */
|
||||
USB_BUS_LOCK(bus);
|
||||
usb_proc_mwait(&bus->non_giant_callback_proc,
|
||||
&hub->tt_msg[0], &hub->tt_msg[1]);
|
||||
USB_BUS_UNLOCK(bus);
|
||||
#endif
|
||||
free(hub, M_USBDEV);
|
||||
sc->sc_udev->hub = NULL;
|
||||
|
||||
@ -2070,9 +2350,10 @@ usbd_transfer_power_ref(struct usb_xfer *xfer, int val)
|
||||
static uint8_t
|
||||
usb_peer_should_wakeup(struct usb_device *udev)
|
||||
{
|
||||
return ((udev->power_mode == USB_POWER_MODE_ON) ||
|
||||
return (((udev->power_mode == USB_POWER_MODE_ON) &&
|
||||
(udev->flags.usb_mode == USB_MODE_HOST)) ||
|
||||
(udev->driver_added_refcount != udev->bus->driver_added_refcount) ||
|
||||
(udev->re_enumerate_wait != 0) ||
|
||||
(udev->re_enumerate_wait != USB_RE_ENUM_DONE) ||
|
||||
(udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
|
||||
(udev->pwr_save.write_refs != 0) ||
|
||||
((udev->pwr_save.read_refs != 0) &&
|
||||
@ -2488,6 +2769,8 @@ usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode)
|
||||
|
||||
#if USB_HAVE_POWERD
|
||||
usb_bus_power_update(udev->bus);
|
||||
#else
|
||||
usb_needs_explore(udev->bus, 0 /* no probe */ );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2526,8 +2809,36 @@ usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode)
|
||||
void
|
||||
usbd_start_re_enumerate(struct usb_device *udev)
|
||||
{
|
||||
if (udev->re_enumerate_wait == 0) {
|
||||
udev->re_enumerate_wait = 1;
|
||||
if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
|
||||
udev->re_enumerate_wait = USB_RE_ENUM_START;
|
||||
usb_needs_explore(udev->bus, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*
|
||||
* usbd_start_set_config
|
||||
*
|
||||
* This function starts setting a USB configuration. This function
|
||||
* does not need to be called BUS-locked. This function does not wait
|
||||
* until the set USB configuratino is completed.
|
||||
*------------------------------------------------------------------------*/
|
||||
usb_error_t
|
||||
usbd_start_set_config(struct usb_device *udev, uint8_t index)
|
||||
{
|
||||
if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
|
||||
if (udev->curr_config_index == index) {
|
||||
/* no change needed */
|
||||
return (0);
|
||||
}
|
||||
udev->next_config_index = index;
|
||||
udev->re_enumerate_wait = USB_RE_ENUM_SET_CONFIG;
|
||||
usb_needs_explore(udev->bus, 0);
|
||||
return (0);
|
||||
} else if (udev->re_enumerate_wait == USB_RE_ENUM_SET_CONFIG) {
|
||||
if (udev->next_config_index == index) {
|
||||
/* no change needed */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (USB_ERR_PENDING_REQUESTS);
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ struct usb_port {
|
||||
#define USB_RESTART_MAX 5
|
||||
uint8_t device_index; /* zero means not valid */
|
||||
enum usb_hc_mode usb_mode; /* host or device mode */
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
struct usb_device_request req_reset_tt __aligned(4);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -44,6 +47,9 @@ struct usb_hub {
|
||||
struct usb_device *hubudev; /* the HUB device */
|
||||
usb_error_t (*explore) (struct usb_device *hub);
|
||||
void *hubsoftc;
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
struct usb_udev_msg tt_msg[2];
|
||||
#endif
|
||||
usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
|
||||
uint16_t portpower; /* mA per USB port */
|
||||
uint8_t isoc_last_time;
|
||||
@ -65,5 +71,6 @@ void usb_bus_power_update(struct usb_bus *bus);
|
||||
void usb_bus_powerd(struct usb_bus *bus);
|
||||
void uhub_root_intr(struct usb_bus *, const uint8_t *, uint8_t);
|
||||
usb_error_t uhub_query_info(struct usb_device *, uint8_t *, uint8_t *);
|
||||
void uhub_explore_handle_re_enumerate(struct usb_device *);
|
||||
|
||||
#endif /* _USB_HUB_H_ */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define _USB_IOCTL_H_
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/* Building "kdump" depends on these includes */
|
||||
|
||||
@ -41,6 +42,16 @@
|
||||
#define USB_GENERIC_NAME "ugen"
|
||||
#define USB_TEMPLATE_SYSCTL "hw.usb.template" /* integer type */
|
||||
|
||||
/*
|
||||
* Align IOCTL structures to hide differences when running 32-bit
|
||||
* programs under 64-bit kernels:
|
||||
*/
|
||||
#ifdef COMPAT_32BIT
|
||||
#define USB_IOCTL_STRUCT_ALIGN(n) __aligned(n)
|
||||
#else
|
||||
#define USB_IOCTL_STRUCT_ALIGN(n)
|
||||
#endif
|
||||
|
||||
/* Definition of valid template sysctl values */
|
||||
|
||||
enum {
|
||||
@ -62,7 +73,7 @@ struct usb_read_dir {
|
||||
#endif
|
||||
uint32_t urd_startentry;
|
||||
uint32_t urd_maxlen;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(8);
|
||||
|
||||
struct usb_ctl_request {
|
||||
#ifdef COMPAT_32BIT
|
||||
@ -74,12 +85,12 @@ struct usb_ctl_request {
|
||||
uint16_t ucr_actlen; /* actual length transferred */
|
||||
uint8_t ucr_addr; /* zero - currently not used */
|
||||
struct usb_device_request ucr_request;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(8);
|
||||
|
||||
struct usb_alt_interface {
|
||||
uint8_t uai_interface_index;
|
||||
uint8_t uai_alt_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_gen_descriptor {
|
||||
#ifdef COMPAT_32BIT
|
||||
@ -98,7 +109,7 @@ struct usb_gen_descriptor {
|
||||
uint8_t ugd_endpt_index;
|
||||
uint8_t ugd_report_type;
|
||||
uint8_t reserved[8];
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(8);
|
||||
|
||||
struct usb_device_info {
|
||||
uint16_t udi_productNo;
|
||||
@ -127,24 +138,33 @@ struct usb_device_info {
|
||||
char udi_vendor[128];
|
||||
char udi_serial[64];
|
||||
char udi_release[8];
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(2);
|
||||
|
||||
#define USB_DEVICE_PORT_PATH_MAX 32
|
||||
|
||||
struct usb_device_port_path {
|
||||
uint8_t udp_bus; /* which bus we are on */
|
||||
uint8_t udp_index; /* which device index */
|
||||
uint8_t udp_port_level; /* how many levels: 0, 1, 2 ... */
|
||||
uint8_t udp_port_no[USB_DEVICE_PORT_PATH_MAX];
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_device_stats {
|
||||
uint32_t uds_requests_ok[4]; /* Indexed by transfer type UE_XXX */
|
||||
uint32_t uds_requests_fail[4]; /* Indexed by transfer type UE_XXX */
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(4);
|
||||
|
||||
struct usb_fs_start {
|
||||
uint8_t ep_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_fs_stop {
|
||||
uint8_t ep_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_fs_complete {
|
||||
uint8_t ep_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
/* This structure is used for all endpoint types */
|
||||
struct usb_fs_endpoint {
|
||||
@ -177,7 +197,7 @@ struct usb_fs_endpoint {
|
||||
/* timeout value for no timeout */
|
||||
#define USB_FS_TIMEOUT_NONE 0
|
||||
int status; /* see USB_ERR_XXX */
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(8);
|
||||
|
||||
struct usb_fs_init {
|
||||
/* userland pointer to endpoints structure */
|
||||
@ -188,11 +208,11 @@ struct usb_fs_init {
|
||||
#endif
|
||||
/* maximum number of endpoints */
|
||||
uint8_t ep_index_max;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(8);
|
||||
|
||||
struct usb_fs_uninit {
|
||||
uint8_t dummy; /* zero */
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_fs_open {
|
||||
#define USB_FS_MAX_BUFSIZE (1 << 18)
|
||||
@ -204,15 +224,20 @@ struct usb_fs_open {
|
||||
uint8_t dev_index; /* currently unused */
|
||||
uint8_t ep_index;
|
||||
uint8_t ep_no; /* bEndpointNumber */
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(4);
|
||||
|
||||
struct usb_fs_open_stream {
|
||||
struct usb_fs_open fs_open;
|
||||
uint16_t stream_id; /* stream ID */
|
||||
} USB_IOCTL_STRUCT_ALIGN(4);
|
||||
|
||||
struct usb_fs_close {
|
||||
uint8_t ep_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_fs_clear_stall_sync {
|
||||
uint8_t ep_index;
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(1);
|
||||
|
||||
struct usb_gen_quirk {
|
||||
uint16_t index; /* Quirk Index */
|
||||
@ -222,11 +247,11 @@ struct usb_gen_quirk {
|
||||
uint16_t bcdDeviceHigh; /* High Device Revision */
|
||||
uint16_t reserved[2];
|
||||
/*
|
||||
* String version of quirk including terminating zero. See UQ_XXX in
|
||||
* "usb_quirk.h".
|
||||
* String version of quirk including terminating zero. See
|
||||
* UQ_XXX in "usb_quirk.h".
|
||||
*/
|
||||
char quirkname[64 - 14];
|
||||
};
|
||||
} USB_IOCTL_STRUCT_ALIGN(2);
|
||||
|
||||
/* USB controller */
|
||||
#define USB_REQUEST _IOWR('U', 1, struct usb_ctl_request)
|
||||
@ -270,7 +295,8 @@ struct usb_gen_quirk {
|
||||
#define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int)
|
||||
#define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t)
|
||||
#define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir)
|
||||
/* 128 - 134 unused */
|
||||
/* 128 - 133 unused */
|
||||
#define USB_GET_DEV_PORT_PATH _IOR ('U', 134, struct usb_device_port_path)
|
||||
#define USB_GET_POWER_USAGE _IOR ('U', 135, int)
|
||||
#define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int)
|
||||
#define USB_SET_TX_TIMEOUT _IOW ('U', 137, int)
|
||||
|
@ -85,7 +85,7 @@ enum {
|
||||
DIR_NONE,
|
||||
};
|
||||
|
||||
#define SCSI_MAX_LEN 0x100
|
||||
#define SCSI_MAX_LEN MAX(0x100, BULK_SIZE)
|
||||
#define SCSI_INQ_LEN 0x24
|
||||
#define SCSI_SENSE_LEN 0xFF
|
||||
|
||||
@ -141,8 +141,8 @@ struct bbb_csw {
|
||||
struct bbb_transfer {
|
||||
struct mtx mtx;
|
||||
struct cv cv;
|
||||
struct bbb_cbw cbw;
|
||||
struct bbb_csw csw;
|
||||
struct bbb_cbw *cbw;
|
||||
struct bbb_csw *csw;
|
||||
|
||||
struct usb_xfer *xfer[ST_MAX];
|
||||
|
||||
@ -152,6 +152,7 @@ struct bbb_transfer {
|
||||
usb_size_t data_rem; /* bytes */
|
||||
usb_timeout_t data_timeout; /* ms */
|
||||
usb_frlength_t actlen; /* bytes */
|
||||
usb_frlength_t buffer_size; /* bytes */
|
||||
|
||||
uint8_t cmd_len; /* bytes */
|
||||
uint8_t dir;
|
||||
@ -160,7 +161,7 @@ struct bbb_transfer {
|
||||
uint8_t status_try;
|
||||
int error;
|
||||
|
||||
uint8_t buffer[SCSI_MAX_LEN] __aligned(4);
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
static usb_callback_t bbb_command_callback;
|
||||
@ -186,7 +187,6 @@ static const struct usb_config bbb_config[ST_MAX] = {
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.bufsize = sizeof(struct bbb_cbw),
|
||||
.flags = {.ext_buffer = 1,},
|
||||
.callback = &bbb_command_callback,
|
||||
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
|
||||
},
|
||||
@ -195,8 +195,8 @@ static const struct usb_config bbb_config[ST_MAX] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.bufsize = BULK_SIZE,
|
||||
.flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
|
||||
.bufsize = SCSI_MAX_LEN,
|
||||
.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
|
||||
.callback = &bbb_data_read_callback,
|
||||
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
|
||||
},
|
||||
@ -214,7 +214,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.bufsize = BULK_SIZE,
|
||||
.bufsize = SCSI_MAX_LEN,
|
||||
.flags = {.ext_buffer = 1,.proxy_buffer = 1,},
|
||||
.callback = &bbb_data_write_callback,
|
||||
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
|
||||
@ -234,7 +234,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.bufsize = sizeof(struct bbb_csw),
|
||||
.flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
|
||||
.flags = {.short_xfer_ok = 1,},
|
||||
.callback = &bbb_status_callback,
|
||||
.timeout = 1 * USB_MS_HZ, /* 1 second */
|
||||
},
|
||||
@ -243,7 +243,6 @@ static const struct usb_config bbb_config[ST_MAX] = {
|
||||
static void
|
||||
bbb_done(struct bbb_transfer *sc, int error)
|
||||
{
|
||||
|
||||
sc->error = error;
|
||||
sc->state = ST_COMMAND;
|
||||
sc->status_try = 1;
|
||||
@ -292,18 +291,19 @@ bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
case USB_ST_SETUP:
|
||||
sc->status_try = 0;
|
||||
tag = UGETDW(sc->cbw.dCBWTag) + 1;
|
||||
USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
|
||||
USETDW(sc->cbw.dCBWTag, tag);
|
||||
USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
|
||||
sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
|
||||
sc->cbw.bCBWLUN = sc->lun;
|
||||
sc->cbw.bCDBLength = sc->cmd_len;
|
||||
if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) {
|
||||
sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB);
|
||||
tag = UGETDW(sc->cbw->dCBWTag) + 1;
|
||||
USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
|
||||
USETDW(sc->cbw->dCBWTag, tag);
|
||||
USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
|
||||
sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
|
||||
sc->cbw->bCBWLUN = sc->lun;
|
||||
sc->cbw->bCDBLength = sc->cmd_len;
|
||||
if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
|
||||
sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
|
||||
DPRINTFN(0, "Truncating long command\n");
|
||||
}
|
||||
usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw));
|
||||
usbd_xfer_set_frame_len(xfer, 0,
|
||||
sizeof(struct bbb_cbw));
|
||||
usbd_transfer_submit(xfer);
|
||||
break;
|
||||
|
||||
@ -390,7 +390,7 @@ bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
if (sc->data_rem == 0) {
|
||||
bbb_transfer_start(sc, ST_STATUS);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (max_bulk > sc->data_rem) {
|
||||
max_bulk = sc->data_rem;
|
||||
@ -398,7 +398,7 @@ bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
usbd_xfer_set_timeout(xfer, sc->data_timeout);
|
||||
usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
|
||||
usbd_transfer_submit(xfer);
|
||||
return;
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
if (error == USB_ERR_CANCELLED) {
|
||||
@ -406,8 +406,7 @@ bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
} else {
|
||||
bbb_transfer_start(sc, ST_DATA_WR_CS);
|
||||
}
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,9 +431,9 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
/* very simple status check */
|
||||
|
||||
if (actlen < (int)sizeof(sc->csw)) {
|
||||
if (actlen < (int)sizeof(struct bbb_csw)) {
|
||||
bbb_done(sc, USB_ERR_SHORT_XFER);
|
||||
} else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
|
||||
} else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
|
||||
bbb_done(sc, 0); /* success */
|
||||
} else {
|
||||
bbb_done(sc, ERR_CSW_FAILED); /* error */
|
||||
@ -442,7 +441,8 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
break;
|
||||
|
||||
case USB_ST_SETUP:
|
||||
usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw));
|
||||
usbd_xfer_set_frame_len(xfer, 0,
|
||||
sizeof(struct bbb_csw));
|
||||
usbd_transfer_submit(xfer);
|
||||
break;
|
||||
|
||||
@ -480,9 +480,9 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
|
||||
sc->data_timeout = (data_timeout + USB_MS_HZ);
|
||||
sc->actlen = 0;
|
||||
sc->cmd_len = cmd_len;
|
||||
memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
|
||||
memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
|
||||
DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
|
||||
memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
|
||||
memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
|
||||
DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
|
||||
|
||||
mtx_lock(&sc->mtx);
|
||||
usbd_transfer_start(sc->xfer[sc->state]);
|
||||
@ -551,6 +551,16 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index)
|
||||
bbb_detach(sc);
|
||||
return (NULL);
|
||||
}
|
||||
/* store pointer to DMA buffers */
|
||||
sc->buffer = usbd_xfer_get_frame_buffer(
|
||||
sc->xfer[ST_DATA_RD], 0);
|
||||
sc->buffer_size =
|
||||
usbd_xfer_max_len(sc->xfer[ST_DATA_RD]);
|
||||
sc->cbw = usbd_xfer_get_frame_buffer(
|
||||
sc->xfer[ST_COMMAND], 0);
|
||||
sc->csw = usbd_xfer_get_frame_buffer(
|
||||
sc->xfer[ST_STATUS], 0);
|
||||
|
||||
return (sc);
|
||||
}
|
||||
|
||||
@ -826,8 +836,8 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
|
||||
* TCTMobile needs DIR_IN flag. To get it, we
|
||||
* supply a dummy data with the command.
|
||||
*/
|
||||
err = bbb_command_start(sc, DIR_IN, 0, &sc->buffer,
|
||||
sizeof(sc->buffer), &scsi_tct_eject,
|
||||
err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
|
||||
sc->buffer_size, &scsi_tct_eject,
|
||||
sizeof(scsi_tct_eject), USB_MS_HZ);
|
||||
break;
|
||||
default:
|
||||
|
@ -503,3 +503,15 @@ usb_proc_rewakeup(struct usb_process *up)
|
||||
cv_signal(&up->up_cv);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_proc_is_called_from
|
||||
*
|
||||
* This function will return non-zero if called from inside the USB
|
||||
* process passed as first argument. Else this function returns zero.
|
||||
*------------------------------------------------------------------------*/
|
||||
int
|
||||
usb_proc_is_called_from(struct usb_process *up)
|
||||
{
|
||||
return (up->up_curtd == curthread);
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ void usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1);
|
||||
void usb_proc_free(struct usb_process *up);
|
||||
void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
|
||||
void usb_proc_rewakeup(struct usb_process *up);
|
||||
int usb_proc_is_called_from(struct usb_process *up);
|
||||
|
||||
void usb_proc_explore_mwait(struct usb_device *, void *, void *);
|
||||
void *usb_proc_explore_msignal(struct usb_device *, void *, void *);
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
#include <dev/usb/usbdi_util.h>
|
||||
#include <dev/usb/usb_ioctl.h>
|
||||
#include <dev/usb/usbhid.h>
|
||||
|
||||
#define USB_DEBUG_VAR usb_debug
|
||||
@ -74,6 +73,11 @@ static int usb_no_cs_fail;
|
||||
SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
|
||||
&usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
|
||||
|
||||
static int usb_full_ddesc;
|
||||
|
||||
SYSCTL_INT(_hw_usb, OID_AUTO, full_ddesc, CTLFLAG_RW,
|
||||
&usb_full_ddesc, 0, "USB always read complete device descriptor, if set");
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
#ifdef USB_REQ_DEBUG
|
||||
/* The following structures are used in connection to fault injection. */
|
||||
@ -712,6 +716,17 @@ done:
|
||||
if ((mtx != NULL) && (mtx != &Giant))
|
||||
mtx_lock(mtx);
|
||||
|
||||
switch (err) {
|
||||
case USB_ERR_NORMAL_COMPLETION:
|
||||
case USB_ERR_SHORT_XFER:
|
||||
case USB_ERR_STALLED:
|
||||
case USB_ERR_CANCELLED:
|
||||
break;
|
||||
default:
|
||||
DPRINTF("I/O error - waiting a bit for TT cleanup\n");
|
||||
usb_pause_mtx(mtx, hz / 16);
|
||||
break;
|
||||
}
|
||||
return ((usb_error_t)err);
|
||||
}
|
||||
|
||||
@ -999,7 +1014,7 @@ usbd_req_get_desc(struct usb_device *udev,
|
||||
USETW(req.wLength, min_len);
|
||||
|
||||
err = usbd_do_request_flags(udev, mtx, &req,
|
||||
desc, 0, NULL, 1000);
|
||||
desc, 0, NULL, 500 /* ms */);
|
||||
|
||||
if (err) {
|
||||
if (!retries) {
|
||||
@ -1884,32 +1899,41 @@ usbd_setup_device_desc(struct usb_device *udev, struct mtx *mtx)
|
||||
*/
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_FULL:
|
||||
case USB_SPEED_LOW:
|
||||
if (usb_full_ddesc != 0) {
|
||||
/* get full device descriptor */
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
if (err == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* get partial device descriptor, some devices crash on this */
|
||||
err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
|
||||
USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
|
||||
if (err != 0) {
|
||||
DPRINTFN(0, "getting device descriptor "
|
||||
"at addr %d failed, %s\n", udev->address,
|
||||
usbd_errstr(err));
|
||||
return (err);
|
||||
}
|
||||
if (err != 0)
|
||||
break;
|
||||
|
||||
/* get the full device descriptor */
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF("Minimum MaxPacketSize is large enough "
|
||||
"to hold the complete device descriptor\n");
|
||||
"to hold the complete device descriptor or "
|
||||
"only once MaxPacketSize choice\n");
|
||||
|
||||
/* get the full device descriptor */
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
|
||||
/* try one more time, if error */
|
||||
if (err != 0)
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
break;
|
||||
}
|
||||
|
||||
/* get the full device descriptor */
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
|
||||
/* try one more time, if error */
|
||||
if (err)
|
||||
err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
|
||||
|
||||
if (err) {
|
||||
DPRINTF("addr=%d, getting full desc failed\n",
|
||||
udev->address);
|
||||
if (err != 0) {
|
||||
DPRINTFN(0, "getting device descriptor "
|
||||
"at addr %d failed, %s\n", udev->address,
|
||||
usbd_errstr(err));
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -1954,6 +1978,7 @@ usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx)
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
retry:
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
/*
|
||||
* Try to reset the High Speed parent HUB of a LOW- or FULL-
|
||||
* speed device, if any.
|
||||
@ -1961,15 +1986,24 @@ retry:
|
||||
if (udev->parent_hs_hub != NULL &&
|
||||
udev->speed != USB_SPEED_HIGH) {
|
||||
DPRINTF("Trying to reset parent High Speed TT.\n");
|
||||
err = usbd_req_reset_tt(udev->parent_hs_hub, NULL,
|
||||
udev->hs_port_no);
|
||||
if (udev->parent_hs_hub == parent_hub &&
|
||||
(uhub_count_active_host_ports(parent_hub, USB_SPEED_LOW) +
|
||||
uhub_count_active_host_ports(parent_hub, USB_SPEED_FULL)) == 1) {
|
||||
/* we can reset the whole TT */
|
||||
err = usbd_req_reset_tt(parent_hub, NULL,
|
||||
udev->hs_port_no);
|
||||
} else {
|
||||
/* only reset a particular device and endpoint */
|
||||
err = usbd_req_clear_tt_buffer(udev->parent_hs_hub, NULL,
|
||||
udev->hs_port_no, old_addr, UE_CONTROL, 0);
|
||||
}
|
||||
if (err) {
|
||||
DPRINTF("Resetting parent High "
|
||||
"Speed TT failed (%s).\n",
|
||||
usbd_errstr(err));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Try to warm reset first */
|
||||
if (parent_hub->speed == USB_SPEED_SUPER)
|
||||
usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);
|
||||
|
@ -334,6 +334,7 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
||||
usb_frcount_t n_frlengths;
|
||||
usb_frcount_t n_frbuffers;
|
||||
usb_frcount_t x;
|
||||
uint16_t maxp_old;
|
||||
uint8_t type;
|
||||
uint8_t zmps;
|
||||
|
||||
@ -419,6 +420,11 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
||||
if (xfer->max_packet_count > parm->hc_max_packet_count) {
|
||||
xfer->max_packet_count = parm->hc_max_packet_count;
|
||||
}
|
||||
|
||||
/* store max packet size value before filtering */
|
||||
|
||||
maxp_old = xfer->max_packet_size;
|
||||
|
||||
/* filter "wMaxPacketSize" according to HC capabilities */
|
||||
|
||||
if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
|
||||
@ -451,6 +457,13 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the max packet size was outside its allowed range
|
||||
* and clamped to a valid value:
|
||||
*/
|
||||
if (maxp_old != xfer->max_packet_size)
|
||||
xfer->flags_int.maxp_was_clamped = 1;
|
||||
|
||||
/* compute "max_frame_size" */
|
||||
|
||||
usbd_update_max_frame_size(xfer);
|
||||
@ -2396,7 +2409,9 @@ usbd_transfer_enqueue(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
|
||||
void
|
||||
usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
struct usb_xfer_root *info = xfer->xroot;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
|
||||
|
||||
DPRINTF("err=%s\n", usbd_errstr(error));
|
||||
|
||||
@ -2410,10 +2425,10 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
|
||||
xfer->flags_int.control_act = 0;
|
||||
return;
|
||||
}
|
||||
/* only set transfer error if not already set */
|
||||
if (!xfer->error) {
|
||||
/* only set transfer error, if not already set */
|
||||
if (xfer->error == USB_ERR_NORMAL_COMPLETION)
|
||||
xfer->error = error;
|
||||
}
|
||||
|
||||
/* stop any callouts */
|
||||
usb_callout_stop(&xfer->timeout_handle);
|
||||
|
||||
@ -2425,14 +2440,14 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
|
||||
usbd_transfer_dequeue(xfer);
|
||||
|
||||
#if USB_HAVE_BUSDMA
|
||||
if (mtx_owned(xfer->xroot->xfer_mtx)) {
|
||||
if (mtx_owned(info->xfer_mtx)) {
|
||||
struct usb_xfer_queue *pq;
|
||||
|
||||
/*
|
||||
* If the private USB lock is not locked, then we assume
|
||||
* that the BUS-DMA load stage has been passed:
|
||||
*/
|
||||
pq = &xfer->xroot->dma_q;
|
||||
pq = &info->dma_q;
|
||||
|
||||
if (pq->curr == xfer) {
|
||||
/* start the next BUS-DMA load, if any */
|
||||
@ -2442,10 +2457,10 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
|
||||
#endif
|
||||
/* keep some statistics */
|
||||
if (xfer->error) {
|
||||
xfer->xroot->bus->stats_err.uds_requests
|
||||
info->bus->stats_err.uds_requests
|
||||
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
|
||||
} else {
|
||||
xfer->xroot->bus->stats_ok.uds_requests
|
||||
info->bus->stats_ok.uds_requests
|
||||
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
|
||||
}
|
||||
|
||||
@ -2685,7 +2700,7 @@ usbd_transfer_timeout_ms(struct usb_xfer *xfer,
|
||||
|
||||
/* defer delay */
|
||||
usb_callout_reset(&xfer->timeout_handle,
|
||||
USB_MS_TO_TICKS(ms), cb, xfer);
|
||||
USB_MS_TO_TICKS(ms) + USB_CALLOUT_ZERO_TICKS, cb, xfer);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -2811,6 +2826,22 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer)
|
||||
/* end of control transfer, if any */
|
||||
xfer->flags_int.control_act = 0;
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
switch (xfer->error) {
|
||||
case USB_ERR_NORMAL_COMPLETION:
|
||||
case USB_ERR_SHORT_XFER:
|
||||
case USB_ERR_STALLED:
|
||||
case USB_ERR_CANCELLED:
|
||||
/* nothing to do */
|
||||
break;
|
||||
default:
|
||||
/* try to reset the TT, if any */
|
||||
USB_BUS_LOCK(bus);
|
||||
uhub_tt_buffer_reset_async_locked(xfer->xroot->udev, xfer->endpoint);
|
||||
USB_BUS_UNLOCK(bus);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* check if we should block the execution queue */
|
||||
if ((xfer->error != USB_ERR_CANCELLED) &&
|
||||
(xfer->flags.pipe_bof)) {
|
||||
@ -3377,3 +3408,13 @@ usbd_xfer_get_timestamp(struct usb_xfer *xfer)
|
||||
{
|
||||
return (xfer->isoc_time_complete);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function returns non-zero if the max packet size
|
||||
* field was clamped to a valid value. Else it returns zero.
|
||||
*/
|
||||
uint8_t
|
||||
usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
|
||||
{
|
||||
return (xfer->flags_int.maxp_was_clamped);
|
||||
}
|
||||
|
@ -558,6 +558,7 @@ int usbd_xfer_is_stalled(struct usb_xfer *xfer);
|
||||
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
|
||||
void usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
|
||||
uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
|
||||
uint8_t usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer);
|
||||
|
||||
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
|
||||
const void *ptr, usb_frlength_t len);
|
||||
@ -574,6 +575,8 @@ void usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset,
|
||||
void usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
|
||||
usb_frlength_t len);
|
||||
void usbd_start_re_enumerate(struct usb_device *udev);
|
||||
usb_error_t
|
||||
usbd_start_set_config(struct usb_device *, uint8_t);
|
||||
|
||||
int usb_fifo_attach(struct usb_device *udev, void *priv_sc,
|
||||
struct mtx *priv_mtx, struct usb_fifo_methods *pm,
|
||||
|
@ -180,9 +180,15 @@
|
||||
#define AMDID2_WDT 0x00002000
|
||||
#define AMDID2_LWP 0x00008000
|
||||
#define AMDID2_FMA4 0x00010000
|
||||
#define AMDID2_TCE 0x00020000
|
||||
#define AMDID2_NODE_ID 0x00080000
|
||||
#define AMDID2_TBM 0x00200000
|
||||
#define AMDID2_TOPOLOGY 0x00400000
|
||||
#define AMDID2_PCXC 0x00800000
|
||||
#define AMDID2_PNXC 0x01000000
|
||||
#define AMDID2_DBE 0x04000000
|
||||
#define AMDID2_PTSC 0x08000000
|
||||
#define AMDID2_PTSCEL2I 0x10000000
|
||||
|
||||
/*
|
||||
* CPUID instruction 1 eax info
|
||||
|
@ -250,9 +250,6 @@ restart:
|
||||
/*
|
||||
* Traverse the (now) ordered list of system initialization tasks.
|
||||
* Perform each task, and continue on to the next task.
|
||||
*
|
||||
* The last item on the list is expected to be the scheduler,
|
||||
* which will not return.
|
||||
*/
|
||||
for (sipp = sysinit; sipp < sysinit_end; sipp++) {
|
||||
|
||||
@ -312,8 +309,14 @@ restart:
|
||||
#endif /* __rtems__ */
|
||||
}
|
||||
|
||||
mtx_assert(&Giant, MA_OWNED | MA_NOTRECURSED);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
#ifndef __rtems__
|
||||
panic("Shouldn't get here!");
|
||||
/*
|
||||
* Now hand over this thread to swapper.
|
||||
*/
|
||||
swapper();
|
||||
/* NOTREACHED*/
|
||||
#endif /* __rtems__ */
|
||||
}
|
||||
@ -358,7 +361,7 @@ static char wit_warn[] =
|
||||
"WARNING: WITNESS option enabled, expect reduced performance.\n";
|
||||
SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_THIRD + 1,
|
||||
print_caddr_t, wit_warn);
|
||||
SYSINIT(witwarn2, SI_SUB_RUN_SCHEDULER, SI_ORDER_THIRD + 1,
|
||||
SYSINIT(witwarn2, SI_SUB_LAST, SI_ORDER_THIRD + 1,
|
||||
print_caddr_t, wit_warn);
|
||||
#endif
|
||||
|
||||
@ -367,7 +370,7 @@ static char diag_warn[] =
|
||||
"WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n";
|
||||
SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_THIRD + 2,
|
||||
print_caddr_t, diag_warn);
|
||||
SYSINIT(diagwarn2, SI_SUB_RUN_SCHEDULER, SI_ORDER_THIRD + 2,
|
||||
SYSINIT(diagwarn2, SI_SUB_LAST, SI_ORDER_THIRD + 2,
|
||||
print_caddr_t, diag_warn);
|
||||
#endif
|
||||
|
||||
@ -494,6 +497,7 @@ proc0_init(void *dummy __unused)
|
||||
|
||||
p->p_sysent = &null_sysvec;
|
||||
p->p_flag = P_SYSTEM | P_INMEM;
|
||||
p->p_flag2 = 0;
|
||||
p->p_state = PRS_NORMAL;
|
||||
knlist_init_mtx(&p->p_klist, &p->p_mtx);
|
||||
STAILQ_INIT(&p->p_ktr);
|
||||
|
@ -464,8 +464,11 @@ filt_proc(struct knote *kn, long hint)
|
||||
if (!(kn->kn_status & KN_DETACHED))
|
||||
knlist_remove_inevent(&p->p_klist, kn);
|
||||
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
|
||||
kn->kn_data = p->p_xstat;
|
||||
kn->kn_ptr.p_proc = NULL;
|
||||
if (kn->kn_fflags & NOTE_EXIT)
|
||||
kn->kn_data = p->p_xstat;
|
||||
if (kn->kn_fflags == 0)
|
||||
kn->kn_flags |= EV_DROP;
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -497,7 +500,7 @@ knote_fork(struct knlist *list, int pid)
|
||||
continue;
|
||||
kq = kn->kn_kq;
|
||||
KQ_LOCK(kq);
|
||||
if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) {
|
||||
if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
|
||||
KQ_UNLOCK(kq);
|
||||
continue;
|
||||
}
|
||||
@ -507,7 +510,7 @@ knote_fork(struct knlist *list, int pid)
|
||||
*/
|
||||
if ((kn->kn_sfflags & NOTE_TRACK) == 0) {
|
||||
kn->kn_status |= KN_HASKQLOCK;
|
||||
if (kn->kn_fop->f_event(kn, NOTE_FORK | pid))
|
||||
if (kn->kn_fop->f_event(kn, NOTE_FORK))
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
kn->kn_status &= ~KN_HASKQLOCK;
|
||||
KQ_UNLOCK(kq);
|
||||
@ -535,10 +538,10 @@ knote_fork(struct knlist *list, int pid)
|
||||
kev.data = kn->kn_id; /* parent */
|
||||
kev.udata = kn->kn_kevent.udata;/* preserve udata */
|
||||
error = kqueue_register(kq, &kev, NULL, 0);
|
||||
if (kn->kn_fop->f_event(kn, NOTE_FORK | pid))
|
||||
KNOTE_ACTIVATE(kn, 0);
|
||||
if (error)
|
||||
kn->kn_fflags |= NOTE_TRACKERR;
|
||||
if (kn->kn_fop->f_event(kn, NOTE_FORK))
|
||||
KNOTE_ACTIVATE(kn, 0);
|
||||
KQ_LOCK(kq);
|
||||
kn->kn_status &= ~KN_INFLUX;
|
||||
KQ_UNLOCK_FLUX(kq);
|
||||
@ -753,11 +756,11 @@ sys_kqueue(struct thread *td, struct kqueue_args *uap)
|
||||
|
||||
#ifndef __rtems__
|
||||
FILEDESC_XLOCK(fdp);
|
||||
SLIST_INSERT_HEAD(&fdp->fd_kqlist, kq, kq_list);
|
||||
TAILQ_INSERT_HEAD(&fdp->fd_kqlist, kq, kq_list);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
#else /* __rtems__ */
|
||||
rtems_libio_lock();
|
||||
SLIST_INSERT_HEAD(&fd_kqlist, kq, kq_list);
|
||||
TAILQ_INSERT_HEAD(&fd_kqlist, kq, kq_list);
|
||||
rtems_libio_unlock();
|
||||
#endif /* __rtems__ */
|
||||
|
||||
@ -1076,12 +1079,13 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
|
||||
struct file *fp;
|
||||
struct knote *kn, *tkn;
|
||||
int error, filt, event;
|
||||
int haskqglobal;
|
||||
int haskqglobal, filedesc_unlock;
|
||||
|
||||
fp = NULL;
|
||||
kn = NULL;
|
||||
error = 0;
|
||||
haskqglobal = 0;
|
||||
filedesc_unlock = 0;
|
||||
|
||||
filt = kev->filter;
|
||||
fops = kqueue_fo_find(filt);
|
||||
@ -1125,6 +1129,13 @@ findkn:
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-lock the filedesc before the global
|
||||
* lock mutex, see the comment in
|
||||
* kqueue_close().
|
||||
*/
|
||||
FILEDESC_XLOCK(td->td_proc->p_fd);
|
||||
filedesc_unlock = 1;
|
||||
KQ_GLOBAL_LOCK(&kq_global, haskqglobal);
|
||||
}
|
||||
|
||||
@ -1154,6 +1165,10 @@ findkn:
|
||||
/* knote is in the process of changing, wait for it to stablize. */
|
||||
if (kn != NULL && (kn->kn_status & KN_INFLUX) == KN_INFLUX) {
|
||||
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
|
||||
if (filedesc_unlock) {
|
||||
FILEDESC_XUNLOCK(td->td_proc->p_fd);
|
||||
filedesc_unlock = 0;
|
||||
}
|
||||
kq->kq_state |= KQ_FLUXWAIT;
|
||||
msleep(kq, &kq->kq_lock, PSOCK | PDROP, "kqflxwt", 0);
|
||||
if (fp != NULL) {
|
||||
@ -1229,7 +1244,7 @@ findkn:
|
||||
* but doing so will not reset any filter which has already been
|
||||
* triggered.
|
||||
*/
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
kn->kn_status |= KN_INFLUX | KN_SCAN;
|
||||
KQ_UNLOCK(kq);
|
||||
KN_LIST_LOCK(kn);
|
||||
kn->kn_kevent.udata = kev->udata;
|
||||
@ -1252,7 +1267,7 @@ done_ev_add:
|
||||
KQ_LOCK(kq);
|
||||
if (event)
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
kn->kn_status &= ~KN_INFLUX;
|
||||
kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
|
||||
KN_LIST_UNLOCK(kn);
|
||||
|
||||
if ((kev->flags & EV_DISABLE) &&
|
||||
@ -1270,6 +1285,8 @@ done_ev_add:
|
||||
|
||||
done:
|
||||
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
|
||||
if (filedesc_unlock)
|
||||
FILEDESC_XUNLOCK(td->td_proc->p_fd);
|
||||
if (fp != NULL)
|
||||
fdrop(fp, td);
|
||||
if (tkn != NULL)
|
||||
@ -1541,7 +1558,21 @@ start:
|
||||
KASSERT((kn->kn_status & KN_INFLUX) == 0,
|
||||
("KN_INFLUX set when not suppose to be"));
|
||||
|
||||
if ((kn->kn_flags & EV_ONESHOT) == EV_ONESHOT) {
|
||||
if ((kn->kn_flags & EV_DROP) == EV_DROP) {
|
||||
kn->kn_status &= ~KN_QUEUED;
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
kq->kq_count--;
|
||||
KQ_UNLOCK(kq);
|
||||
/*
|
||||
* We don't need to lock the list since we've marked
|
||||
* it _INFLUX.
|
||||
*/
|
||||
if (!(kn->kn_status & KN_DETACHED))
|
||||
kn->kn_fop->f_detach(kn);
|
||||
knote_drop(kn, td);
|
||||
KQ_LOCK(kq);
|
||||
continue;
|
||||
} else if ((kn->kn_flags & EV_ONESHOT) == EV_ONESHOT) {
|
||||
kn->kn_status &= ~KN_QUEUED;
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
kq->kq_count--;
|
||||
@ -1557,7 +1588,7 @@ start:
|
||||
KQ_LOCK(kq);
|
||||
kn = NULL;
|
||||
} else {
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
kn->kn_status |= KN_INFLUX | KN_SCAN;
|
||||
KQ_UNLOCK(kq);
|
||||
if ((kn->kn_status & KN_KQUEUE) == KN_KQUEUE)
|
||||
KQ_GLOBAL_LOCK(&kq_global, haskqglobal);
|
||||
@ -1566,7 +1597,8 @@ start:
|
||||
KQ_LOCK(kq);
|
||||
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
|
||||
kn->kn_status &=
|
||||
~(KN_QUEUED | KN_ACTIVE | KN_INFLUX);
|
||||
~(KN_QUEUED | KN_ACTIVE | KN_INFLUX |
|
||||
KN_SCAN);
|
||||
kq->kq_count--;
|
||||
KN_LIST_UNLOCK(kn);
|
||||
influx = 1;
|
||||
@ -1596,7 +1628,7 @@ start:
|
||||
} else
|
||||
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
|
||||
|
||||
kn->kn_status &= ~(KN_INFLUX);
|
||||
kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
|
||||
KN_LIST_UNLOCK(kn);
|
||||
influx = 1;
|
||||
}
|
||||
@ -1788,6 +1820,7 @@ kqueue_close(struct file *fp, struct thread *td)
|
||||
struct knote *kn;
|
||||
int i;
|
||||
int error;
|
||||
int filedesc_unlock;
|
||||
|
||||
#ifdef __rtems__
|
||||
/* FIXME: Move this to the RTEMS close() function */
|
||||
@ -1797,6 +1830,7 @@ kqueue_close(struct file *fp, struct thread *td)
|
||||
if ((error = kqueue_acquire(fp, &kq)))
|
||||
return error;
|
||||
|
||||
filedesc_unlock = 0;
|
||||
KQ_LOCK(kq);
|
||||
|
||||
KASSERT((kq->kq_state & KQ_CLOSING) != KQ_CLOSING,
|
||||
@ -1863,12 +1897,24 @@ kqueue_close(struct file *fp, struct thread *td)
|
||||
KQ_UNLOCK(kq);
|
||||
|
||||
#ifndef __rtems__
|
||||
FILEDESC_XLOCK(fdp);
|
||||
SLIST_REMOVE(&fdp->fd_kqlist, kq, kqueue, kq_list);
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
/*
|
||||
* We could be called due to the knote_drop() doing fdrop(),
|
||||
* called from kqueue_register(). In this case the global
|
||||
* lock is owned, and filedesc sx is locked before, to not
|
||||
* take the sleepable lock after non-sleepable.
|
||||
*/
|
||||
if (!sx_xlocked(FILEDESC_LOCK(fdp))) {
|
||||
FILEDESC_XLOCK(fdp);
|
||||
filedesc_unlock = 1;
|
||||
} else
|
||||
filedesc_unlock = 0;
|
||||
TAILQ_REMOVE(&fdp->fd_kqlist, kq, kq_list);
|
||||
if (filedesc_unlock)
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
#else /* __rtems__ */
|
||||
(void)filedesc_unlock;
|
||||
rtems_libio_lock();
|
||||
SLIST_REMOVE(&fd_kqlist, kq, kqueue, kq_list);
|
||||
TAILQ_REMOVE(&fd_kqlist, kq, kq_list);
|
||||
rtems_libio_unlock();
|
||||
#endif /* __rtems__ */
|
||||
|
||||
@ -1966,28 +2012,33 @@ knote(struct knlist *list, long hint, int lockflags)
|
||||
*/
|
||||
SLIST_FOREACH(kn, &list->kl_list, kn_selnext) {
|
||||
kq = kn->kn_kq;
|
||||
if ((kn->kn_status & KN_INFLUX) != KN_INFLUX) {
|
||||
KQ_LOCK(kq);
|
||||
if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
|
||||
/*
|
||||
* Do not process the influx notes, except for
|
||||
* the influx coming from the kq unlock in the
|
||||
* kqueue_scan(). In the later case, we do
|
||||
* not interfere with the scan, since the code
|
||||
* fragment in kqueue_scan() locks the knlist,
|
||||
* and cannot proceed until we finished.
|
||||
*/
|
||||
KQ_UNLOCK(kq);
|
||||
} else if ((lockflags & KNF_NOKQLOCK) != 0) {
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
KQ_UNLOCK(kq);
|
||||
error = kn->kn_fop->f_event(kn, hint);
|
||||
KQ_LOCK(kq);
|
||||
if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) {
|
||||
KQ_UNLOCK(kq);
|
||||
} else if ((lockflags & KNF_NOKQLOCK) != 0) {
|
||||
kn->kn_status |= KN_INFLUX;
|
||||
KQ_UNLOCK(kq);
|
||||
error = kn->kn_fop->f_event(kn, hint);
|
||||
KQ_LOCK(kq);
|
||||
kn->kn_status &= ~KN_INFLUX;
|
||||
if (error)
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
KQ_UNLOCK_FLUX(kq);
|
||||
} else {
|
||||
kn->kn_status |= KN_HASKQLOCK;
|
||||
if (kn->kn_fop->f_event(kn, hint))
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
kn->kn_status &= ~KN_HASKQLOCK;
|
||||
KQ_UNLOCK(kq);
|
||||
}
|
||||
kn->kn_status &= ~KN_INFLUX;
|
||||
if (error)
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
KQ_UNLOCK_FLUX(kq);
|
||||
} else {
|
||||
kn->kn_status |= KN_HASKQLOCK;
|
||||
if (kn->kn_fop->f_event(kn, hint))
|
||||
KNOTE_ACTIVATE(kn, 1);
|
||||
kn->kn_status &= ~KN_HASKQLOCK;
|
||||
KQ_UNLOCK(kq);
|
||||
}
|
||||
kq = NULL;
|
||||
}
|
||||
if ((lockflags & KNF_LISTLOCKED) == 0)
|
||||
list->kl_unlock(list->kl_lockarg);
|
||||
@ -2231,11 +2282,11 @@ knote_fdclose(struct thread *td, int fd)
|
||||
* since filedesc is locked.
|
||||
*/
|
||||
#ifndef __rtems__
|
||||
SLIST_FOREACH(kq, &fdp->fd_kqlist, kq_list) {
|
||||
TAILQ_FOREACH(kq, &fdp->fd_kqlist, kq_list) {
|
||||
#else /* __rtems__ */
|
||||
/* FIXME: Use separate lock? */
|
||||
rtems_libio_lock();
|
||||
SLIST_FOREACH(kq, &fd_kqlist, kq_list) {
|
||||
TAILQ_FOREACH(kq, &fd_kqlist, kq_list) {
|
||||
#endif /* __rtems__ */
|
||||
KQ_LOCK(kq);
|
||||
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/libkern.h>
|
||||
@ -71,17 +72,6 @@ SYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW,
|
||||
&kld_debug, 0, "Set various levels of KLD debug");
|
||||
#endif
|
||||
|
||||
#define KLD_LOCK() sx_xlock(&kld_sx)
|
||||
#define KLD_UNLOCK() sx_xunlock(&kld_sx)
|
||||
#define KLD_DOWNGRADE() sx_downgrade(&kld_sx)
|
||||
#define KLD_LOCK_READ() sx_slock(&kld_sx)
|
||||
#define KLD_UNLOCK_READ() sx_sunlock(&kld_sx)
|
||||
#define KLD_LOCKED() sx_xlocked(&kld_sx)
|
||||
#define KLD_LOCK_ASSERT() do { \
|
||||
if (!cold) \
|
||||
sx_assert(&kld_sx, SX_XLOCKED); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* static char *linker_search_path(const char *name, struct mod_depend
|
||||
* *verinfo);
|
||||
@ -123,7 +113,8 @@ static int linker_no_more_classes = 0;
|
||||
#define LINKER_GET_NEXT_FILE_ID(a) do { \
|
||||
linker_file_t lftmp; \
|
||||
\
|
||||
KLD_LOCK_ASSERT(); \
|
||||
if (!cold) \
|
||||
sx_assert(&kld_sx, SA_XLOCKED); \
|
||||
retry: \
|
||||
TAILQ_FOREACH(lftmp, &linker_files, link) { \
|
||||
if (next_file_id == lftmp->id) { \
|
||||
@ -210,6 +201,8 @@ linker_file_sysinit(linker_file_t lf)
|
||||
KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
|
||||
if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
/*
|
||||
@ -235,6 +228,7 @@ linker_file_sysinit(linker_file_t lf)
|
||||
* Traverse the (now) ordered list of system initialization tasks.
|
||||
* Perform each task, and continue on to the next task.
|
||||
*/
|
||||
sx_xunlock(&kld_sx);
|
||||
mtx_lock(&Giant);
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
if ((*sipp)->subsystem == SI_SUB_DUMMY)
|
||||
@ -244,6 +238,7 @@ linker_file_sysinit(linker_file_t lf)
|
||||
(*((*sipp)->func)) ((*sipp)->udata);
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
sx_xlock(&kld_sx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -254,6 +249,8 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
|
||||
if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
|
||||
NULL) != 0)
|
||||
return;
|
||||
@ -281,6 +278,7 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
* Traverse the (now) ordered list of system initialization tasks.
|
||||
* Perform each task, and continue on to the next task.
|
||||
*/
|
||||
sx_xunlock(&kld_sx);
|
||||
mtx_lock(&Giant);
|
||||
for (sipp = start; sipp < stop; sipp++) {
|
||||
if ((*sipp)->subsystem == SI_SUB_DUMMY)
|
||||
@ -290,6 +288,7 @@ linker_file_sysuninit(linker_file_t lf)
|
||||
(*((*sipp)->func)) ((*sipp)->udata);
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
sx_xlock(&kld_sx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -301,13 +300,17 @@ linker_file_register_sysctls(linker_file_t lf)
|
||||
("linker_file_register_sysctls: registering SYSCTLs for %s\n",
|
||||
lf->filename));
|
||||
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
|
||||
if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
|
||||
sx_xunlock(&kld_sx);
|
||||
sysctl_lock();
|
||||
for (oidp = start; oidp < stop; oidp++)
|
||||
sysctl_register_oid(*oidp);
|
||||
sysctl_unlock();
|
||||
sx_xlock(&kld_sx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -318,13 +321,17 @@ linker_file_unregister_sysctls(linker_file_t lf)
|
||||
KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
|
||||
" for %s\n", lf->filename));
|
||||
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
|
||||
if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
|
||||
return;
|
||||
|
||||
sx_xunlock(&kld_sx);
|
||||
sysctl_lock();
|
||||
for (oidp = start; oidp < stop; oidp++)
|
||||
sysctl_unregister_oid(*oidp);
|
||||
sysctl_unlock();
|
||||
sx_xlock(&kld_sx);
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
|
||||
@ -339,6 +346,8 @@ linker_file_register_modules(linker_file_t lf)
|
||||
" in %s\n", lf->filename));
|
||||
|
||||
#ifndef __rtems__
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
|
||||
if (linker_file_lookup_set(lf, "modmetadata_set", &start,
|
||||
&stop, NULL) != 0) {
|
||||
/*
|
||||
@ -379,7 +388,9 @@ linker_init_kernel_modules(void)
|
||||
{
|
||||
|
||||
#ifndef __rtems__
|
||||
sx_xlock(&kld_sx);
|
||||
linker_file_register_modules(linker_kernel_file);
|
||||
sx_xunlock(&kld_sx);
|
||||
#else /* __rtems__ */
|
||||
linker_file_register_modules(NULL);
|
||||
#endif /* __rtems__ */
|
||||
@ -400,7 +411,7 @@ linker_load_file(const char *filename, linker_file_t *result)
|
||||
if (prison0.pr_securelevel > 0)
|
||||
return (EPERM);
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
lf = linker_find_file_by_name(filename);
|
||||
if (lf) {
|
||||
KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
|
||||
@ -434,10 +445,8 @@ linker_load_file(const char *filename, linker_file_t *result)
|
||||
return (error);
|
||||
}
|
||||
modules = !TAILQ_EMPTY(&lf->modules);
|
||||
KLD_UNLOCK();
|
||||
linker_file_register_sysctls(lf);
|
||||
linker_file_sysinit(lf);
|
||||
KLD_LOCK();
|
||||
lf->flags |= LINKER_FILE_LINKED;
|
||||
|
||||
/*
|
||||
@ -449,6 +458,7 @@ linker_load_file(const char *filename, linker_file_t *result)
|
||||
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
|
||||
return (ENOEXEC);
|
||||
}
|
||||
EVENTHANDLER_INVOKE(kld_load, lf);
|
||||
*result = lf;
|
||||
return (0);
|
||||
}
|
||||
@ -488,16 +498,16 @@ linker_reference_module(const char *modname, struct mod_depend *verinfo,
|
||||
modlist_t mod;
|
||||
int error;
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
|
||||
*result = mod->container;
|
||||
(*result)->refs++;
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
error = linker_load_module(NULL, modname, NULL, verinfo, result);
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -508,13 +518,13 @@ linker_release_module(const char *modname, struct mod_depend *verinfo,
|
||||
modlist_t mod;
|
||||
int error;
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
if (lf == NULL) {
|
||||
KASSERT(modname != NULL,
|
||||
("linker_release_module: no file or name"));
|
||||
mod = modlist_lookup2(modname, verinfo);
|
||||
if (mod == NULL) {
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (ESRCH);
|
||||
}
|
||||
lf = mod->container;
|
||||
@ -522,7 +532,7 @@ linker_release_module(const char *modname, struct mod_depend *verinfo,
|
||||
KASSERT(modname == NULL && verinfo == NULL,
|
||||
("linker_release_module: both file and name"));
|
||||
error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -535,7 +545,7 @@ linker_find_file_by_name(const char *filename)
|
||||
koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
|
||||
sprintf(koname, "%s.ko", filename);
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
TAILQ_FOREACH(lf, &linker_files, link) {
|
||||
if (strcmp(lf->filename, koname) == 0)
|
||||
break;
|
||||
@ -551,7 +561,7 @@ linker_find_file_by_id(int fileid)
|
||||
{
|
||||
linker_file_t lf;
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
TAILQ_FOREACH(lf, &linker_files, link)
|
||||
if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
|
||||
break;
|
||||
@ -564,13 +574,13 @@ linker_file_foreach(linker_predicate_t *predicate, void *context)
|
||||
linker_file_t lf;
|
||||
int retval = 0;
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
TAILQ_FOREACH(lf, &linker_files, link) {
|
||||
retval = predicate(lf, context);
|
||||
if (retval != 0)
|
||||
break;
|
||||
}
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
@ -580,7 +590,8 @@ linker_make_file(const char *pathname, linker_class_t lc)
|
||||
linker_file_t lf;
|
||||
const char *filename;
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
if (!cold)
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
filename = linker_basename(pathname);
|
||||
|
||||
KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
|
||||
@ -596,8 +607,6 @@ linker_make_file(const char *pathname, linker_class_t lc)
|
||||
lf->ndeps = 0;
|
||||
lf->deps = NULL;
|
||||
lf->loadcnt = ++loadcnt;
|
||||
lf->sdt_probes = NULL;
|
||||
lf->sdt_nprobes = 0;
|
||||
STAILQ_INIT(&lf->common);
|
||||
TAILQ_INIT(&lf->modules);
|
||||
TAILQ_INSERT_TAIL(&linker_files, lf, link);
|
||||
@ -616,7 +625,7 @@ linker_file_unload(linker_file_t file, int flags)
|
||||
if (prison0.pr_securelevel > 0)
|
||||
return (EPERM);
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
|
||||
|
||||
/* Easy case of just dropping a reference. */
|
||||
@ -625,6 +634,12 @@ linker_file_unload(linker_file_t file, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Give eventhandlers a chance to prevent the unload. */
|
||||
error = 0;
|
||||
EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
|
||||
if (error != 0)
|
||||
return (EBUSY);
|
||||
|
||||
KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
|
||||
" informing modules\n"));
|
||||
|
||||
@ -689,10 +704,8 @@ linker_file_unload(linker_file_t file, int flags)
|
||||
*/
|
||||
if (file->flags & LINKER_FILE_LINKED) {
|
||||
file->flags &= ~LINKER_FILE_LINKED;
|
||||
KLD_UNLOCK();
|
||||
linker_file_sysuninit(file);
|
||||
linker_file_unregister_sysctls(file);
|
||||
KLD_LOCK();
|
||||
}
|
||||
TAILQ_REMOVE(&linker_files, file, link);
|
||||
|
||||
@ -708,6 +721,10 @@ linker_file_unload(linker_file_t file, int flags)
|
||||
}
|
||||
|
||||
LINKER_UNLOAD(file);
|
||||
|
||||
EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
|
||||
file->size);
|
||||
|
||||
if (file->filename) {
|
||||
free(file->filename, M_LINKER);
|
||||
file->filename = NULL;
|
||||
@ -731,18 +748,9 @@ linker_file_add_dependency(linker_file_t file, linker_file_t dep)
|
||||
{
|
||||
linker_file_t *newdeps;
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
file->deps = realloc(file->deps, (file->ndeps + 1) * sizeof(*newdeps),
|
||||
M_LINKER, M_WAITOK | M_ZERO);
|
||||
if (newdeps == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
if (file->deps) {
|
||||
bcopy(file->deps, newdeps,
|
||||
file->ndeps * sizeof(linker_file_t *));
|
||||
free(file->deps, M_LINKER);
|
||||
}
|
||||
file->deps = newdeps;
|
||||
file->deps[file->ndeps] = dep;
|
||||
file->ndeps++;
|
||||
KLD_DPF(FILE, ("linker_file_add_dependency:"
|
||||
@ -761,15 +769,9 @@ int
|
||||
linker_file_lookup_set(linker_file_t file, const char *name,
|
||||
void *firstp, void *lastp, int *countp)
|
||||
{
|
||||
int error, locked;
|
||||
|
||||
locked = KLD_LOCKED();
|
||||
if (!locked)
|
||||
KLD_LOCK();
|
||||
error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
|
||||
if (!locked)
|
||||
KLD_UNLOCK();
|
||||
return (error);
|
||||
sx_assert(&kld_sx, SA_LOCKED);
|
||||
return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -788,12 +790,12 @@ linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
|
||||
caddr_t sym;
|
||||
int locked;
|
||||
|
||||
locked = KLD_LOCKED();
|
||||
locked = sx_xlocked(&kld_sx);
|
||||
if (!locked)
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
sym = linker_file_lookup_symbol_internal(file, name, deps);
|
||||
if (!locked)
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (sym);
|
||||
}
|
||||
|
||||
@ -807,7 +809,7 @@ linker_file_lookup_symbol_internal(linker_file_t file, const char *name,
|
||||
size_t common_size = 0;
|
||||
int i;
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
|
||||
file, name, deps));
|
||||
|
||||
@ -1007,9 +1009,9 @@ linker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
|
||||
{
|
||||
int error;
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
error = linker_debug_search_symbol_name(value, buf, buflen, offset);
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1019,9 +1021,6 @@ linker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
|
||||
int
|
||||
kern_kldload(struct thread *td, const char *file, int *fileid)
|
||||
{
|
||||
#ifdef HWPMC_HOOKS
|
||||
struct pmckern_map_in pkm;
|
||||
#endif
|
||||
const char *kldname, *modname;
|
||||
linker_file_t lf;
|
||||
int error;
|
||||
@ -1051,24 +1050,16 @@ kern_kldload(struct thread *td, const char *file, int *fileid)
|
||||
modname = file;
|
||||
}
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
error = linker_load_module(kldname, modname, NULL, NULL, &lf);
|
||||
if (error) {
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
goto done;
|
||||
}
|
||||
lf->userrefs++;
|
||||
if (fileid != NULL)
|
||||
*fileid = lf->id;
|
||||
#ifdef HWPMC_HOOKS
|
||||
KLD_DOWNGRADE();
|
||||
pkm.pm_file = lf->filename;
|
||||
pkm.pm_address = (uintptr_t) lf->address;
|
||||
PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
|
||||
KLD_UNLOCK_READ();
|
||||
#else
|
||||
KLD_UNLOCK();
|
||||
#endif
|
||||
sx_xunlock(&kld_sx);
|
||||
|
||||
done:
|
||||
CURVNET_RESTORE();
|
||||
@ -1097,9 +1088,6 @@ sys_kldload(struct thread *td, struct kldload_args *uap)
|
||||
int
|
||||
kern_kldunload(struct thread *td, int fileid, int flags)
|
||||
{
|
||||
#ifdef HWPMC_HOOKS
|
||||
struct pmckern_map_out pkm;
|
||||
#endif
|
||||
linker_file_t lf;
|
||||
int error = 0;
|
||||
|
||||
@ -1110,17 +1098,12 @@ kern_kldunload(struct thread *td, int fileid, int flags)
|
||||
return (error);
|
||||
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
lf = linker_find_file_by_id(fileid);
|
||||
if (lf) {
|
||||
KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
|
||||
|
||||
/* Check if there are DTrace probes enabled on this file. */
|
||||
if (lf->nenabled > 0) {
|
||||
printf("kldunload: attempt to unload file that has"
|
||||
" DTrace probes enabled\n");
|
||||
error = EBUSY;
|
||||
} else if (lf->userrefs == 0) {
|
||||
if (lf->userrefs == 0) {
|
||||
/*
|
||||
* XXX: maybe LINKER_UNLOAD_FORCE should override ?
|
||||
*/
|
||||
@ -1128,11 +1111,6 @@ kern_kldunload(struct thread *td, int fileid, int flags)
|
||||
" loaded by the kernel\n");
|
||||
error = EBUSY;
|
||||
} else {
|
||||
#ifdef HWPMC_HOOKS
|
||||
/* Save data needed by hwpmc(4) before unloading. */
|
||||
pkm.pm_address = (uintptr_t) lf->address;
|
||||
pkm.pm_size = lf->size;
|
||||
#endif
|
||||
lf->userrefs--;
|
||||
error = linker_file_unload(lf, flags);
|
||||
if (error)
|
||||
@ -1140,17 +1118,8 @@ kern_kldunload(struct thread *td, int fileid, int flags)
|
||||
}
|
||||
} else
|
||||
error = ENOENT;
|
||||
sx_xunlock(&kld_sx);
|
||||
|
||||
#ifdef HWPMC_HOOKS
|
||||
if (error == 0) {
|
||||
KLD_DOWNGRADE();
|
||||
PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
|
||||
KLD_UNLOCK_READ();
|
||||
} else
|
||||
KLD_UNLOCK();
|
||||
#else
|
||||
KLD_UNLOCK();
|
||||
#endif
|
||||
CURVNET_RESTORE();
|
||||
return (error);
|
||||
}
|
||||
@ -1193,13 +1162,13 @@ sys_kldfind(struct thread *td, struct kldfind_args *uap)
|
||||
goto out;
|
||||
|
||||
filename = linker_basename(pathname);
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
lf = linker_find_file_by_name(filename);
|
||||
if (lf)
|
||||
td->td_retval[0] = lf->id;
|
||||
else
|
||||
error = ENOENT;
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
out:
|
||||
free(pathname, M_TEMP);
|
||||
return (error);
|
||||
@ -1217,7 +1186,7 @@ sys_kldnext(struct thread *td, struct kldnext_args *uap)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
if (uap->fileid == 0)
|
||||
lf = TAILQ_FIRST(&linker_files);
|
||||
else {
|
||||
@ -1238,7 +1207,7 @@ sys_kldnext(struct thread *td, struct kldnext_args *uap)
|
||||
else
|
||||
td->td_retval[0] = 0;
|
||||
out:
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1277,10 +1246,10 @@ kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
lf = linker_find_file_by_id(fileid);
|
||||
if (lf == NULL) {
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
@ -1298,7 +1267,7 @@ kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
|
||||
if (namelen > MAXPATHLEN)
|
||||
namelen = MAXPATHLEN;
|
||||
bcopy(lf->pathname, &stat->pathname[0], namelen);
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
|
||||
td->td_retval[0] = 0;
|
||||
return (0);
|
||||
@ -1317,7 +1286,7 @@ sys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
lf = linker_find_file_by_id(uap->fileid);
|
||||
if (lf) {
|
||||
MOD_SLOCK;
|
||||
@ -1329,7 +1298,7 @@ sys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
|
||||
MOD_SUNLOCK;
|
||||
} else
|
||||
error = ENOENT;
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1357,7 +1326,7 @@ sys_kldsym(struct thread *td, struct kldsym_args *uap)
|
||||
symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
||||
if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
|
||||
goto out;
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
if (uap->fileid != 0) {
|
||||
lf = linker_find_file_by_id(uap->fileid);
|
||||
if (lf == NULL)
|
||||
@ -1383,7 +1352,7 @@ sys_kldsym(struct thread *td, struct kldsym_args *uap)
|
||||
if (lf == NULL)
|
||||
error = ENOENT;
|
||||
}
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
out:
|
||||
free(symstr, M_TEMP);
|
||||
return (error);
|
||||
@ -1492,6 +1461,7 @@ linker_preload(void *arg)
|
||||
error = 0;
|
||||
|
||||
modptr = NULL;
|
||||
sx_xlock(&kld_sx);
|
||||
while ((modptr = preload_search_next_name(modptr)) != NULL) {
|
||||
modname = (char *)preload_search_info(modptr, MODINFO_NAME);
|
||||
modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
|
||||
@ -1673,6 +1643,7 @@ fail:
|
||||
TAILQ_REMOVE(&depended_files, lf, loaded);
|
||||
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
|
||||
}
|
||||
sx_xunlock(&kld_sx);
|
||||
/* woohoo! we made it! */
|
||||
}
|
||||
|
||||
@ -1978,7 +1949,7 @@ linker_hwpmc_list_objects(void)
|
||||
int i, nmappings;
|
||||
|
||||
nmappings = 0;
|
||||
KLD_LOCK_READ();
|
||||
sx_slock(&kld_sx);
|
||||
TAILQ_FOREACH(lf, &linker_files, link)
|
||||
nmappings++;
|
||||
|
||||
@ -1993,7 +1964,7 @@ linker_hwpmc_list_objects(void)
|
||||
kobase[i].pm_address = (uintptr_t)lf->address;
|
||||
i++;
|
||||
}
|
||||
KLD_UNLOCK_READ();
|
||||
sx_sunlock(&kld_sx);
|
||||
|
||||
KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
|
||||
|
||||
@ -2019,7 +1990,7 @@ linker_load_module(const char *kldname, const char *modname,
|
||||
char *pathname;
|
||||
int error;
|
||||
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
if (modname == NULL) {
|
||||
/*
|
||||
* We have to load KLD
|
||||
@ -2093,7 +2064,7 @@ linker_load_dependencies(linker_file_t lf)
|
||||
/*
|
||||
* All files are dependant on /kernel.
|
||||
*/
|
||||
KLD_LOCK_ASSERT();
|
||||
sx_assert(&kld_sx, SA_XLOCKED);
|
||||
if (linker_kernel_file) {
|
||||
linker_kernel_file->refs++;
|
||||
error = linker_file_add_dependency(lf, linker_kernel_file);
|
||||
@ -2185,16 +2156,16 @@ sysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
|
||||
error = sysctl_wire_old_buffer(req, 0);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
KLD_LOCK();
|
||||
sx_xlock(&kld_sx);
|
||||
TAILQ_FOREACH(lf, &linker_files, link) {
|
||||
error = LINKER_EACH_FUNCTION_NAME(lf,
|
||||
sysctl_kern_function_list_iterate, req);
|
||||
if (error) {
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
KLD_UNLOCK();
|
||||
sx_xunlock(&kld_sx);
|
||||
return (SYSCTL_OUT(req, "", 1));
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005,
|
||||
* Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved.
|
||||
* Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -49,9 +49,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/uma.h>
|
||||
#include <vm/uma_int.h>
|
||||
#include <vm/uma_dbg.h>
|
||||
#ifdef __rtems__
|
||||
#include <rtems/bsd/bsd.h>
|
||||
#endif /* __rtems__ */
|
||||
|
||||
/*
|
||||
* In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA
|
||||
@ -78,7 +82,7 @@ __FBSDID("$FreeBSD$");
|
||||
* [ Cluster Zone ] [ Zone ] [ Mbuf Master Zone ]
|
||||
* | \________ |
|
||||
* [ Cluster Keg ] \ /
|
||||
* | [ Mbuf Keg ]
|
||||
* | [ Mbuf Keg ]
|
||||
* [ Cluster Slabs ] |
|
||||
* | [ Mbuf Slabs ]
|
||||
* \____________(VM)_________________/
|
||||
@ -98,39 +102,69 @@ __FBSDID("$FreeBSD$");
|
||||
*
|
||||
*/
|
||||
|
||||
int nmbufs; /* limits number of mbufs */
|
||||
int nmbclusters; /* limits number of mbuf clusters */
|
||||
int nmbjumbop; /* limits number of page size jumbo clusters */
|
||||
int nmbjumbo9; /* limits number of 9k jumbo clusters */
|
||||
int nmbjumbo16; /* limits number of 16k jumbo clusters */
|
||||
struct mbstat mbstat;
|
||||
|
||||
static quad_t maxmbufmem; /* overall real memory limit for all mbufs */
|
||||
|
||||
SYSCTL_QUAD(_kern_ipc, OID_AUTO, maxmbufmem, CTLFLAG_RDTUN, &maxmbufmem, 0,
|
||||
"Maximum real memory allocateable to various mbuf types");
|
||||
|
||||
/*
|
||||
* tunable_mbinit() has to be run before init_maxsockets() thus
|
||||
* the SYSINIT order below is SI_ORDER_MIDDLE while init_maxsockets()
|
||||
* runs at SI_ORDER_ANY.
|
||||
* tunable_mbinit() has to be run before any mbuf allocations are done.
|
||||
*/
|
||||
static void
|
||||
tunable_mbinit(void *dummy)
|
||||
{
|
||||
#ifndef __rtems__
|
||||
quad_t realmem;
|
||||
|
||||
/*
|
||||
* The default limit for all mbuf related memory is 1/2 of all
|
||||
* available kernel memory (physical or kmem).
|
||||
* At most it can be 3/4 of available kernel memory.
|
||||
*/
|
||||
realmem = qmin((quad_t)physmem * PAGE_SIZE,
|
||||
vm_map_max(kmem_map) - vm_map_min(kmem_map));
|
||||
maxmbufmem = realmem / 2;
|
||||
TUNABLE_QUAD_FETCH("kern.ipc.maxmbufmem", &maxmbufmem);
|
||||
if (maxmbufmem > realmem / 4 * 3)
|
||||
maxmbufmem = realmem / 4 * 3;
|
||||
#else /* __rtems__ */
|
||||
maxmbufmem = rtems_bsd_get_allocator_domain_size(
|
||||
RTEMS_BSD_ALLOCATOR_DOMAIN_MBUF);
|
||||
#endif /* __rtems__ */
|
||||
|
||||
/* This has to be done before VM init. */
|
||||
TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters);
|
||||
if (nmbclusters == 0)
|
||||
nmbclusters = 1024 + maxusers * 64;
|
||||
nmbclusters = maxmbufmem / MCLBYTES / 4;
|
||||
|
||||
TUNABLE_INT_FETCH("kern.ipc.nmbjumbop", &nmbjumbop);
|
||||
if (nmbjumbop == 0)
|
||||
nmbjumbop = nmbclusters / 2;
|
||||
nmbjumbop = maxmbufmem / MJUMPAGESIZE / 4;
|
||||
|
||||
TUNABLE_INT_FETCH("kern.ipc.nmbjumbo9", &nmbjumbo9);
|
||||
if (nmbjumbo9 == 0)
|
||||
nmbjumbo9 = nmbclusters / 4;
|
||||
nmbjumbo9 = maxmbufmem / MJUM9BYTES / 6;
|
||||
|
||||
TUNABLE_INT_FETCH("kern.ipc.nmbjumbo16", &nmbjumbo16);
|
||||
if (nmbjumbo16 == 0)
|
||||
nmbjumbo16 = nmbclusters / 8;
|
||||
nmbjumbo16 = maxmbufmem / MJUM16BYTES / 6;
|
||||
|
||||
/*
|
||||
* We need at least as many mbufs as we have clusters of
|
||||
* the various types added together.
|
||||
*/
|
||||
TUNABLE_INT_FETCH("kern.ipc.nmbufs", &nmbufs);
|
||||
if (nmbufs < nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16)
|
||||
nmbufs = lmax(maxmbufmem / MSIZE / 5,
|
||||
nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16);
|
||||
}
|
||||
SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
|
||||
SYSINIT(tunable_mbinit, SI_SUB_KMEM, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
|
||||
|
||||
static int
|
||||
sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
|
||||
@ -138,11 +172,12 @@ sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
|
||||
int error, newnmbclusters;
|
||||
|
||||
newnmbclusters = nmbclusters;
|
||||
error = sysctl_handle_int(oidp, &newnmbclusters, 0, req);
|
||||
if (error == 0 && req->newptr) {
|
||||
if (newnmbclusters > nmbclusters) {
|
||||
error = sysctl_handle_int(oidp, &newnmbclusters, 0, req);
|
||||
if (error == 0 && req->newptr && newnmbclusters != nmbclusters) {
|
||||
if (newnmbclusters > nmbclusters &&
|
||||
nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) {
|
||||
nmbclusters = newnmbclusters;
|
||||
uma_zone_set_max(zone_clust, nmbclusters);
|
||||
nmbclusters = uma_zone_set_max(zone_clust, nmbclusters);
|
||||
#ifndef __rtems__
|
||||
EVENTHANDLER_INVOKE(nmbclusters_change);
|
||||
#endif /* __rtems__ */
|
||||
@ -161,11 +196,12 @@ sysctl_nmbjumbop(SYSCTL_HANDLER_ARGS)
|
||||
int error, newnmbjumbop;
|
||||
|
||||
newnmbjumbop = nmbjumbop;
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbop, 0, req);
|
||||
if (error == 0 && req->newptr) {
|
||||
if (newnmbjumbop> nmbjumbop) {
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbop, 0, req);
|
||||
if (error == 0 && req->newptr && newnmbjumbop != nmbjumbop) {
|
||||
if (newnmbjumbop > nmbjumbop &&
|
||||
nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) {
|
||||
nmbjumbop = newnmbjumbop;
|
||||
uma_zone_set_max(zone_jumbop, nmbjumbop);
|
||||
nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop);
|
||||
} else
|
||||
error = EINVAL;
|
||||
}
|
||||
@ -173,8 +209,7 @@ sysctl_nmbjumbop(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbop, CTLTYPE_INT|CTLFLAG_RW,
|
||||
&nmbjumbop, 0, sysctl_nmbjumbop, "IU",
|
||||
"Maximum number of mbuf page size jumbo clusters allowed");
|
||||
|
||||
"Maximum number of mbuf page size jumbo clusters allowed");
|
||||
|
||||
static int
|
||||
sysctl_nmbjumbo9(SYSCTL_HANDLER_ARGS)
|
||||
@ -182,11 +217,12 @@ sysctl_nmbjumbo9(SYSCTL_HANDLER_ARGS)
|
||||
int error, newnmbjumbo9;
|
||||
|
||||
newnmbjumbo9 = nmbjumbo9;
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbo9, 0, req);
|
||||
if (error == 0 && req->newptr) {
|
||||
if (newnmbjumbo9> nmbjumbo9) {
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbo9, 0, req);
|
||||
if (error == 0 && req->newptr && newnmbjumbo9 != nmbjumbo9) {
|
||||
if (newnmbjumbo9 > nmbjumbo9 &&
|
||||
nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) {
|
||||
nmbjumbo9 = newnmbjumbo9;
|
||||
uma_zone_set_max(zone_jumbo9, nmbjumbo9);
|
||||
nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9);
|
||||
} else
|
||||
error = EINVAL;
|
||||
}
|
||||
@ -194,7 +230,7 @@ sysctl_nmbjumbo9(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbo9, CTLTYPE_INT|CTLFLAG_RW,
|
||||
&nmbjumbo9, 0, sysctl_nmbjumbo9, "IU",
|
||||
"Maximum number of mbuf 9k jumbo clusters allowed");
|
||||
"Maximum number of mbuf 9k jumbo clusters allowed");
|
||||
|
||||
static int
|
||||
sysctl_nmbjumbo16(SYSCTL_HANDLER_ARGS)
|
||||
@ -202,11 +238,12 @@ sysctl_nmbjumbo16(SYSCTL_HANDLER_ARGS)
|
||||
int error, newnmbjumbo16;
|
||||
|
||||
newnmbjumbo16 = nmbjumbo16;
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbo16, 0, req);
|
||||
if (error == 0 && req->newptr) {
|
||||
if (newnmbjumbo16> nmbjumbo16) {
|
||||
error = sysctl_handle_int(oidp, &newnmbjumbo16, 0, req);
|
||||
if (error == 0 && req->newptr && newnmbjumbo16 != nmbjumbo16) {
|
||||
if (newnmbjumbo16 > nmbjumbo16 &&
|
||||
nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) {
|
||||
nmbjumbo16 = newnmbjumbo16;
|
||||
uma_zone_set_max(zone_jumbo16, nmbjumbo16);
|
||||
nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16);
|
||||
} else
|
||||
error = EINVAL;
|
||||
}
|
||||
@ -216,7 +253,26 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbo16, CTLTYPE_INT|CTLFLAG_RW,
|
||||
&nmbjumbo16, 0, sysctl_nmbjumbo16, "IU",
|
||||
"Maximum number of mbuf 16k jumbo clusters allowed");
|
||||
|
||||
static int
|
||||
sysctl_nmbufs(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error, newnmbufs;
|
||||
|
||||
newnmbufs = nmbufs;
|
||||
error = sysctl_handle_int(oidp, &newnmbufs, 0, req);
|
||||
if (error == 0 && req->newptr && newnmbufs != nmbufs) {
|
||||
if (newnmbufs > nmbufs) {
|
||||
nmbufs = newnmbufs;
|
||||
nmbufs = uma_zone_set_max(zone_mbuf, nmbufs);
|
||||
EVENTHANDLER_INVOKE(nmbufs_change);
|
||||
} else
|
||||
error = EINVAL;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbufs, CTLTYPE_INT|CTLFLAG_RW,
|
||||
&nmbufs, 0, sysctl_nmbufs, "IU",
|
||||
"Maximum number of mbufs allowed");
|
||||
|
||||
SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat,
|
||||
"Mbuf general information and statistics");
|
||||
@ -245,7 +301,6 @@ static int mb_zinit_pack(void *, int, int);
|
||||
static void mb_zfini_pack(void *, int);
|
||||
|
||||
static void mb_reclaim(void *);
|
||||
static void mbuf_init(void *);
|
||||
static void *mbuf_jumbo_alloc(uma_zone_t, int, uint8_t *, int);
|
||||
|
||||
/* Ensure that MSIZE doesn't break dtom() - it must be a power of 2 */
|
||||
@ -254,7 +309,6 @@ CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
|
||||
/*
|
||||
* Initialize FreeBSD Network buffer allocation.
|
||||
*/
|
||||
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
|
||||
static void
|
||||
mbuf_init(void *dummy)
|
||||
{
|
||||
@ -270,6 +324,8 @@ mbuf_init(void *dummy)
|
||||
NULL, NULL,
|
||||
#endif
|
||||
MSIZE - 1, UMA_ZONE_MAXBUCKET);
|
||||
if (nmbufs > 0)
|
||||
nmbufs = uma_zone_set_max(zone_mbuf, nmbufs);
|
||||
|
||||
zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES,
|
||||
mb_ctor_clust, mb_dtor_clust,
|
||||
@ -280,7 +336,7 @@ mbuf_init(void *dummy)
|
||||
#endif
|
||||
UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
|
||||
if (nmbclusters > 0)
|
||||
uma_zone_set_max(zone_clust, nmbclusters);
|
||||
nmbclusters = uma_zone_set_max(zone_clust, nmbclusters);
|
||||
|
||||
zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
|
||||
mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
|
||||
@ -295,7 +351,7 @@ mbuf_init(void *dummy)
|
||||
#endif
|
||||
UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
|
||||
if (nmbjumbop > 0)
|
||||
uma_zone_set_max(zone_jumbop, nmbjumbop);
|
||||
nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop);
|
||||
|
||||
zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES,
|
||||
mb_ctor_clust, mb_dtor_clust,
|
||||
@ -305,9 +361,9 @@ mbuf_init(void *dummy)
|
||||
NULL, NULL,
|
||||
#endif
|
||||
UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
|
||||
if (nmbjumbo9 > 0)
|
||||
uma_zone_set_max(zone_jumbo9, nmbjumbo9);
|
||||
uma_zone_set_allocf(zone_jumbo9, mbuf_jumbo_alloc);
|
||||
if (nmbjumbo9 > 0)
|
||||
nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9);
|
||||
|
||||
zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES,
|
||||
mb_ctor_clust, mb_dtor_clust,
|
||||
@ -317,9 +373,9 @@ mbuf_init(void *dummy)
|
||||
NULL, NULL,
|
||||
#endif
|
||||
UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
|
||||
if (nmbjumbo16 > 0)
|
||||
uma_zone_set_max(zone_jumbo16, nmbjumbo16);
|
||||
uma_zone_set_allocf(zone_jumbo16, mbuf_jumbo_alloc);
|
||||
if (nmbjumbo16 > 0)
|
||||
nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16);
|
||||
|
||||
zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int),
|
||||
NULL, NULL,
|
||||
@ -357,6 +413,7 @@ mbuf_init(void *dummy)
|
||||
mbstat.sf_iocnt = 0;
|
||||
mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
|
||||
}
|
||||
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
|
||||
|
||||
/*
|
||||
* UMA backend page allocator for the jumbo frame zones.
|
||||
@ -445,7 +502,7 @@ static void
|
||||
mb_dtor_mbuf(void *mem, int size, void *arg)
|
||||
{
|
||||
struct mbuf *m;
|
||||
unsigned long flags;
|
||||
unsigned long flags;
|
||||
|
||||
m = (struct mbuf *)mem;
|
||||
flags = (unsigned long)arg;
|
||||
|
@ -271,6 +271,13 @@ SYSCTL_PROC(_hw, HW_MACHINE_ARCH, machine_arch, CTLTYPE_STRING | CTLFLAG_RD,
|
||||
NULL, 0, sysctl_hw_machine_arch, "A", "System architecture");
|
||||
#endif /* __rtems__ */
|
||||
|
||||
SYSCTL_STRING(_kern, OID_AUTO, supported_archs, CTLFLAG_RD | CTLFLAG_MPSAFE,
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
MACHINE_ARCH " " MACHINE_ARCH32, 0, "Supported architectures for binaries");
|
||||
#else
|
||||
MACHINE_ARCH, 0, "Supported architectures for binaries");
|
||||
#endif
|
||||
|
||||
static int
|
||||
sysctl_hostname(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
@ -60,6 +60,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#define MAX_CLOCKS (CLOCK_MONOTONIC+1)
|
||||
#define CPUCLOCK_BIT 0x80000000
|
||||
#define CPUCLOCK_PROCESS_BIT 0x40000000
|
||||
#define CPUCLOCK_ID_MASK (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT))
|
||||
#define MAKE_THREAD_CPUCLOCK(tid) (CPUCLOCK_BIT|(tid))
|
||||
#define MAKE_PROCESS_CPUCLOCK(pid) \
|
||||
(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT|(pid))
|
||||
|
||||
#ifndef __rtems__
|
||||
static struct kclock posix_clocks[MAX_CLOCKS];
|
||||
@ -96,9 +102,6 @@ static int realtimer_settime(struct itimer *, int,
|
||||
static int realtimer_delete(struct itimer *);
|
||||
static void realtimer_clocktime(clockid_t, struct timespec *);
|
||||
static void realtimer_expire(void *);
|
||||
static int kern_timer_create(struct thread *, clockid_t,
|
||||
struct sigevent *, int *, int);
|
||||
static int kern_timer_delete(struct thread *, int);
|
||||
|
||||
int register_posix_clock(int, struct kclock *);
|
||||
void itimer_fire(struct itimer *it);
|
||||
@ -169,6 +172,60 @@ settime(struct thread *td, struct timeval *tv)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct clock_getcpuclockid2_args {
|
||||
id_t id;
|
||||
int which,
|
||||
clockid_t *clock_id;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_clock_getcpuclockid2(struct thread *td, struct clock_getcpuclockid2_args *uap)
|
||||
{
|
||||
clockid_t clk_id;
|
||||
int error;
|
||||
|
||||
error = kern_clock_getcpuclockid2(td, uap->id, uap->which, &clk_id);
|
||||
if (error == 0)
|
||||
error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_clock_getcpuclockid2(struct thread *td, id_t id, int which,
|
||||
clockid_t *clk_id)
|
||||
{
|
||||
struct proc *p;
|
||||
pid_t pid;
|
||||
lwpid_t tid;
|
||||
int error;
|
||||
|
||||
switch (which) {
|
||||
case CPUCLOCK_WHICH_PID:
|
||||
if (id != 0) {
|
||||
p = pfind(id);
|
||||
if (p == NULL)
|
||||
return (ESRCH);
|
||||
error = p_cansee(td, p);
|
||||
PROC_UNLOCK(p);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
pid = id;
|
||||
} else {
|
||||
pid = td->td_proc->p_pid;
|
||||
}
|
||||
*clk_id = MAKE_PROCESS_CPUCLOCK(pid);
|
||||
return (0);
|
||||
case CPUCLOCK_WHICH_TID:
|
||||
tid = id == 0 ? td->td_tid : id;
|
||||
*clk_id = MAKE_THREAD_CPUCLOCK(tid);
|
||||
return (0);
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct clock_gettime_args {
|
||||
clockid_t clock_id;
|
||||
@ -192,12 +249,80 @@ sys_clock_gettime(struct thread *td, struct clock_gettime_args *uap)
|
||||
#endif
|
||||
|
||||
#ifndef __rtems__
|
||||
static inline void
|
||||
cputick2timespec(uint64_t runtime, struct timespec *ats)
|
||||
{
|
||||
runtime = cputick2usec(runtime);
|
||||
ats->tv_sec = runtime / 1000000;
|
||||
ats->tv_nsec = runtime % 1000000 * 1000;
|
||||
}
|
||||
|
||||
static void
|
||||
get_thread_cputime(struct thread *targettd, struct timespec *ats)
|
||||
{
|
||||
uint64_t runtime, curtime, switchtime;
|
||||
|
||||
if (targettd == NULL) { /* current thread */
|
||||
critical_enter();
|
||||
switchtime = PCPU_GET(switchtime);
|
||||
curtime = cpu_ticks();
|
||||
runtime = curthread->td_runtime;
|
||||
critical_exit();
|
||||
runtime += curtime - switchtime;
|
||||
} else {
|
||||
thread_lock(targettd);
|
||||
runtime = targettd->td_runtime;
|
||||
thread_unlock(targettd);
|
||||
}
|
||||
cputick2timespec(runtime, ats);
|
||||
}
|
||||
|
||||
static void
|
||||
get_process_cputime(struct proc *targetp, struct timespec *ats)
|
||||
{
|
||||
uint64_t runtime;
|
||||
struct rusage ru;
|
||||
|
||||
PROC_SLOCK(targetp);
|
||||
rufetch(targetp, &ru);
|
||||
runtime = targetp->p_rux.rux_runtime;
|
||||
PROC_SUNLOCK(targetp);
|
||||
cputick2timespec(runtime, ats);
|
||||
}
|
||||
|
||||
static int
|
||||
get_cputime(struct thread *td, clockid_t clock_id, struct timespec *ats)
|
||||
{
|
||||
struct proc *p, *p2;
|
||||
struct thread *td2;
|
||||
lwpid_t tid;
|
||||
pid_t pid;
|
||||
int error;
|
||||
|
||||
p = td->td_proc;
|
||||
if ((clock_id & CPUCLOCK_PROCESS_BIT) == 0) {
|
||||
tid = clock_id & CPUCLOCK_ID_MASK;
|
||||
td2 = tdfind(tid, p->p_pid);
|
||||
if (td2 == NULL)
|
||||
return (EINVAL);
|
||||
get_thread_cputime(td2, ats);
|
||||
PROC_UNLOCK(td2->td_proc);
|
||||
} else {
|
||||
pid = clock_id & CPUCLOCK_ID_MASK;
|
||||
error = pget(pid, PGET_CANSEE, &p2);
|
||||
if (error != 0)
|
||||
return (EINVAL);
|
||||
get_process_cputime(p2, ats);
|
||||
PROC_UNLOCK(p2);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats)
|
||||
{
|
||||
struct timeval sys, user;
|
||||
struct proc *p;
|
||||
uint64_t runtime, curtime, switchtime;
|
||||
|
||||
p = td->td_proc;
|
||||
switch (clock_id) {
|
||||
@ -240,17 +365,17 @@ kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats)
|
||||
ats->tv_nsec = 0;
|
||||
break;
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
critical_enter();
|
||||
switchtime = PCPU_GET(switchtime);
|
||||
curtime = cpu_ticks();
|
||||
runtime = td->td_runtime;
|
||||
critical_exit();
|
||||
runtime = cputick2usec(runtime + curtime - switchtime);
|
||||
ats->tv_sec = runtime / 1000000;
|
||||
ats->tv_nsec = runtime % 1000000 * 1000;
|
||||
get_thread_cputime(NULL, ats);
|
||||
break;
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
PROC_LOCK(p);
|
||||
get_process_cputime(p, ats);
|
||||
PROC_UNLOCK(p);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
if ((int)clock_id >= 0)
|
||||
return (EINVAL);
|
||||
return (get_cputime(td, clock_id, ats));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -348,12 +473,16 @@ kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts)
|
||||
ts->tv_nsec = 0;
|
||||
break;
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
cputime:
|
||||
/* sync with cputick2usec */
|
||||
ts->tv_nsec = 1000000 / cpu_tickrate();
|
||||
if (ts->tv_nsec == 0)
|
||||
ts->tv_nsec = 1000;
|
||||
break;
|
||||
default:
|
||||
if ((int)clock_id < 0)
|
||||
goto cputime;
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
@ -939,31 +1068,30 @@ struct ktimer_create_args {
|
||||
int
|
||||
sys_ktimer_create(struct thread *td, struct ktimer_create_args *uap)
|
||||
{
|
||||
struct sigevent *evp1, ev;
|
||||
struct sigevent *evp, ev;
|
||||
int id;
|
||||
int error;
|
||||
|
||||
if (uap->evp != NULL) {
|
||||
if (uap->evp == NULL) {
|
||||
evp = NULL;
|
||||
} else {
|
||||
error = copyin(uap->evp, &ev, sizeof(ev));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
evp1 = &ev;
|
||||
} else
|
||||
evp1 = NULL;
|
||||
|
||||
error = kern_timer_create(td, uap->clock_id, evp1, &id, -1);
|
||||
|
||||
evp = &ev;
|
||||
}
|
||||
error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);
|
||||
if (error == 0) {
|
||||
error = copyout(&id, uap->timerid, sizeof(int));
|
||||
if (error != 0)
|
||||
kern_timer_delete(td, id);
|
||||
kern_ktimer_delete(td, id);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
kern_timer_create(struct thread *td, clockid_t clock_id,
|
||||
struct sigevent *evp, int *timerid, int preset_id)
|
||||
int
|
||||
kern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp,
|
||||
int *timerid, int preset_id)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct itimer *it;
|
||||
@ -1078,7 +1206,8 @@ struct ktimer_delete_args {
|
||||
int
|
||||
sys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap)
|
||||
{
|
||||
return (kern_timer_delete(td, uap->timerid));
|
||||
|
||||
return (kern_ktimer_delete(td, uap->timerid));
|
||||
}
|
||||
|
||||
static struct itimer *
|
||||
@ -1100,8 +1229,8 @@ itimer_find(struct proc *p, int timerid)
|
||||
return (it);
|
||||
}
|
||||
|
||||
static int
|
||||
kern_timer_delete(struct thread *td, int timerid)
|
||||
int
|
||||
kern_ktimer_delete(struct thread *td, int timerid)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct itimer *it;
|
||||
@ -1143,35 +1272,40 @@ struct ktimer_settime_args {
|
||||
int
|
||||
sys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct itimer *it;
|
||||
struct itimerspec val, oval, *ovalp;
|
||||
int error;
|
||||
|
||||
error = copyin(uap->value, &val, sizeof(val));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (uap->ovalue != NULL)
|
||||
ovalp = &oval;
|
||||
else
|
||||
ovalp = NULL;
|
||||
ovalp = uap->ovalue != NULL ? &oval : NULL;
|
||||
error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);
|
||||
if (error == 0 && uap->ovalue != NULL)
|
||||
error = copyout(ovalp, uap->ovalue, sizeof(*ovalp));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_ktimer_settime(struct thread *td, int timer_id, int flags,
|
||||
struct itimerspec *val, struct itimerspec *oval)
|
||||
{
|
||||
struct proc *p;
|
||||
struct itimer *it;
|
||||
int error;
|
||||
|
||||
p = td->td_proc;
|
||||
PROC_LOCK(p);
|
||||
if (uap->timerid < 3 ||
|
||||
(it = itimer_find(p, uap->timerid)) == NULL) {
|
||||
if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
|
||||
PROC_UNLOCK(p);
|
||||
error = EINVAL;
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
itimer_enter(it);
|
||||
error = CLOCK_CALL(it->it_clockid, timer_settime,
|
||||
(it, uap->flags, &val, ovalp));
|
||||
error = CLOCK_CALL(it->it_clockid, timer_settime, (it,
|
||||
flags, val, oval));
|
||||
itimer_leave(it);
|
||||
ITIMER_UNLOCK(it);
|
||||
}
|
||||
if (error == 0 && uap->ovalue != NULL)
|
||||
error = copyout(ovalp, uap->ovalue, sizeof(*ovalp));
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1184,26 +1318,34 @@ struct ktimer_gettime_args {
|
||||
int
|
||||
sys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap)
|
||||
{
|
||||
struct proc *p = td->td_proc;
|
||||
struct itimer *it;
|
||||
struct itimerspec val;
|
||||
int error;
|
||||
|
||||
error = kern_ktimer_gettime(td, uap->timerid, &val);
|
||||
if (error == 0)
|
||||
error = copyout(&val, uap->value, sizeof(val));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_ktimer_gettime(struct thread *td, int timer_id, struct itimerspec *val)
|
||||
{
|
||||
struct proc *p;
|
||||
struct itimer *it;
|
||||
int error;
|
||||
|
||||
p = td->td_proc;
|
||||
PROC_LOCK(p);
|
||||
if (uap->timerid < 3 ||
|
||||
(it = itimer_find(p, uap->timerid)) == NULL) {
|
||||
if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
|
||||
PROC_UNLOCK(p);
|
||||
error = EINVAL;
|
||||
} else {
|
||||
PROC_UNLOCK(p);
|
||||
itimer_enter(it);
|
||||
error = CLOCK_CALL(it->it_clockid, timer_gettime,
|
||||
(it, &val));
|
||||
error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, val));
|
||||
itimer_leave(it);
|
||||
ITIMER_UNLOCK(it);
|
||||
}
|
||||
if (error == 0)
|
||||
error = copyout(&val, uap->value, sizeof(val));
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1498,7 +1640,7 @@ itimers_event_hook_exit(void *arg, struct proc *p)
|
||||
panic("unhandled event");
|
||||
for (; i < TIMER_MAX; ++i) {
|
||||
if ((it = its->its_timers[i]) != NULL)
|
||||
kern_timer_delete(curthread, i);
|
||||
kern_ktimer_delete(curthread, i);
|
||||
}
|
||||
if (its->its_timers[0] == NULL &&
|
||||
its->its_timers[1] == NULL &&
|
||||
|
@ -66,11 +66,9 @@ __FBSDID("$FreeBSD$");
|
||||
#define ncallout 16
|
||||
#endif /* __rtems__ */
|
||||
SDT_PROVIDER_DEFINE(callout_execute);
|
||||
SDT_PROBE_DEFINE(callout_execute, kernel, , callout_start, callout-start);
|
||||
SDT_PROBE_ARGTYPE(callout_execute, kernel, , callout_start, 0,
|
||||
SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__start,
|
||||
"struct callout *");
|
||||
SDT_PROBE_DEFINE(callout_execute, kernel, , callout_end, callout-end);
|
||||
SDT_PROBE_ARGTYPE(callout_execute, kernel, , callout_end, 0,
|
||||
SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__end,
|
||||
"struct callout *");
|
||||
|
||||
static int avg_depth;
|
||||
@ -251,7 +249,7 @@ rtems_bsd_timeout_init_late(void *unused)
|
||||
SYSINIT(rtems_bsd_timeout_early, SI_SUB_VM, SI_ORDER_FIRST,
|
||||
rtems_bsd_timeout_init_early, NULL);
|
||||
|
||||
SYSINIT(rtems_bsd_timeout_late, SI_SUB_RUN_SCHEDULER, SI_ORDER_FIRST,
|
||||
SYSINIT(rtems_bsd_timeout_late, SI_SUB_LAST, SI_ORDER_FIRST,
|
||||
rtems_bsd_timeout_init_late, NULL);
|
||||
|
||||
static void
|
||||
@ -580,11 +578,11 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc, int *mpcalls,
|
||||
#endif
|
||||
#ifndef __rtems__
|
||||
THREAD_NO_SLEEPING();
|
||||
SDT_PROBE(callout_execute, kernel, , callout_start, c, 0, 0, 0, 0);
|
||||
SDT_PROBE(callout_execute, kernel, , callout__start, c, 0, 0, 0, 0);
|
||||
#endif /* __rtems__ */
|
||||
c_func(c_arg);
|
||||
#ifndef __rtems__
|
||||
SDT_PROBE(callout_execute, kernel, , callout_end, c, 0, 0, 0, 0);
|
||||
SDT_PROBE(callout_execute, kernel, , callout__end, c, 0, 0, 0, 0);
|
||||
THREAD_SLEEPING_OK();
|
||||
#endif /* __rtems__ */
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -943,11 +941,13 @@ _callout_stop_safe(c, safe)
|
||||
struct callout *c;
|
||||
int safe;
|
||||
{
|
||||
#ifndef __rtems__
|
||||
struct callout_cpu *cc, *old_cc;
|
||||
struct lock_class *class;
|
||||
#ifndef __rtems__
|
||||
int use_lock, sq_locked;
|
||||
#else /* __rtems__ */
|
||||
struct callout_cpu *cc;
|
||||
struct lock_class *class;
|
||||
int use_lock;
|
||||
#endif /* __rtems__ */
|
||||
|
||||
|
@ -12,9 +12,6 @@
|
||||
* 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
|
||||
@ -69,6 +66,7 @@ struct lock_class *lock_classes[LOCK_CLASS_MAX + 1] = {
|
||||
&lock_class_sx,
|
||||
#ifndef __rtems__
|
||||
&lock_class_rm,
|
||||
&lock_class_rm_sleepable,
|
||||
#endif /* __rtems__ */
|
||||
&lock_class_rw,
|
||||
#ifndef __rtems__
|
||||
|
@ -453,7 +453,7 @@ rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
|
||||
mtx_lock(rm->rm_mtx);
|
||||
|
||||
for (r = TAILQ_FIRST(&rm->rm_list);
|
||||
r && r->r_end < start;
|
||||
r && r->r_end < start + count - 1;
|
||||
r = TAILQ_NEXT(r, r_link))
|
||||
;
|
||||
|
||||
@ -463,6 +463,11 @@ rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
|
||||
}
|
||||
|
||||
amask = (1ul << RF_ALIGNMENT(flags)) - 1;
|
||||
if (start > ULONG_MAX - amask) {
|
||||
DPRINTF(("start+amask would wrap around\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If bound is 0, bmask will also be 0 */
|
||||
bmask = ~(bound - 1);
|
||||
/*
|
||||
@ -470,11 +475,20 @@ rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
|
||||
*/
|
||||
for (s = r; s; s = TAILQ_NEXT(s, r_link)) {
|
||||
DPRINTF(("considering [%#lx, %#lx]\n", s->r_start, s->r_end));
|
||||
if (s->r_start + count - 1 > end) {
|
||||
/*
|
||||
* The resource list is sorted, so there is no point in
|
||||
* searching further once r_start is too large.
|
||||
*/
|
||||
if (s->r_start > end - (count - 1)) {
|
||||
DPRINTF(("s->r_start (%#lx) + count - 1> end (%#lx)\n",
|
||||
s->r_start, end));
|
||||
break;
|
||||
}
|
||||
if (s->r_start > ULONG_MAX - amask) {
|
||||
DPRINTF(("s->r_start (%#lx) + amask (%#lx) too large\n",
|
||||
s->r_start, amask));
|
||||
break;
|
||||
}
|
||||
if (s->r_flags & RF_ALLOCATED) {
|
||||
DPRINTF(("region is allocated\n"));
|
||||
continue;
|
||||
@ -585,15 +599,10 @@ rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
|
||||
if ((flags & (RF_SHAREABLE | RF_TIMESHARE)) == 0)
|
||||
goto out;
|
||||
|
||||
for (s = r; s; s = TAILQ_NEXT(s, r_link)) {
|
||||
if (s->r_start > end)
|
||||
break;
|
||||
if ((s->r_flags & flags) != flags)
|
||||
continue;
|
||||
rstart = ulmax(s->r_start, start);
|
||||
rend = ulmin(s->r_end, ulmax(start + count - 1, end));
|
||||
if (s->r_start >= start && s->r_end <= end
|
||||
&& (s->r_end - s->r_start + 1) == count &&
|
||||
for (s = r; s && s->r_end <= end; s = TAILQ_NEXT(s, r_link)) {
|
||||
if ((s->r_flags & flags) == flags &&
|
||||
s->r_start >= start &&
|
||||
(s->r_end - s->r_start + 1) == count &&
|
||||
(s->r_start & amask) == 0 &&
|
||||
((s->r_start ^ s->r_end) & bmask) == 0) {
|
||||
rv = int_alloc_resource(M_NOWAIT);
|
||||
|
@ -708,9 +708,10 @@ sbuf_finish(struct sbuf *s)
|
||||
#ifdef _KERNEL
|
||||
return (s->s_error);
|
||||
#else
|
||||
errno = s->s_error;
|
||||
if (s->s_error)
|
||||
if (s->s_error != 0) {
|
||||
errno = s->s_error;
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
@ -291,6 +291,15 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
|
||||
return (res);
|
||||
}
|
||||
|
||||
static void
|
||||
taskqueue_drain_running(struct taskqueue *queue)
|
||||
{
|
||||
|
||||
while (!TAILQ_EMPTY(&queue->tq_active))
|
||||
TQ_SLEEP(queue, &queue->tq_active, &queue->tq_mutex,
|
||||
PWAIT, "-", 0);
|
||||
}
|
||||
|
||||
void
|
||||
taskqueue_block(struct taskqueue *queue)
|
||||
{
|
||||
@ -343,6 +352,8 @@ taskqueue_run_locked(struct taskqueue *queue)
|
||||
wakeup(task);
|
||||
}
|
||||
TAILQ_REMOVE(&queue->tq_active, &tb, tb_link);
|
||||
if (TAILQ_EMPTY(&queue->tq_active))
|
||||
wakeup(&queue->tq_active);
|
||||
}
|
||||
|
||||
void
|
||||
@ -383,11 +394,9 @@ taskqueue_cancel_locked(struct taskqueue *queue, struct task *task,
|
||||
int
|
||||
taskqueue_cancel(struct taskqueue *queue, struct task *task, u_int *pendp)
|
||||
{
|
||||
u_int pending;
|
||||
int error;
|
||||
|
||||
TQ_LOCK(queue);
|
||||
pending = task->ta_pending;
|
||||
error = taskqueue_cancel_locked(queue, task, pendp);
|
||||
TQ_UNLOCK(queue);
|
||||
|
||||
@ -430,6 +439,27 @@ taskqueue_drain(struct taskqueue *queue, struct task *task)
|
||||
TQ_UNLOCK(queue);
|
||||
}
|
||||
|
||||
void
|
||||
taskqueue_drain_all(struct taskqueue *queue)
|
||||
{
|
||||
struct task *task;
|
||||
|
||||
#ifndef __rtems__
|
||||
if (!queue->tq_spin)
|
||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__);
|
||||
#endif /* __rtems__ */
|
||||
|
||||
TQ_LOCK(queue);
|
||||
task = STAILQ_LAST(&queue->tq_queue, task, ta_link);
|
||||
if (task != NULL)
|
||||
while (task->ta_pending != 0)
|
||||
TQ_SLEEP(queue, task, &queue->tq_mutex, PWAIT, "-", 0);
|
||||
taskqueue_drain_running(queue);
|
||||
KASSERT(STAILQ_EMPTY(&queue->tq_queue),
|
||||
("taskqueue queue is not empty after draining"));
|
||||
TQ_UNLOCK(queue);
|
||||
}
|
||||
|
||||
void
|
||||
taskqueue_drain_timeout(struct taskqueue *queue,
|
||||
struct timeout_task *timeout_task)
|
||||
@ -614,7 +644,6 @@ taskqueue_member(struct taskqueue *queue, struct thread *td)
|
||||
{
|
||||
int i, j, ret = 0;
|
||||
|
||||
TQ_LOCK(queue);
|
||||
for (i = 0, j = 0; ; i++) {
|
||||
if (queue->tq_threads[i] == NULL)
|
||||
continue;
|
||||
@ -625,6 +654,5 @@ taskqueue_member(struct taskqueue *queue, struct thread *td)
|
||||
if (++j >= queue->tq_tcount)
|
||||
break;
|
||||
}
|
||||
TQ_UNLOCK(queue);
|
||||
return (ret);
|
||||
}
|
||||
|
@ -83,6 +83,10 @@ __FBSDID("$FreeBSD$");
|
||||
int iosize_max_clamp = 1;
|
||||
SYSCTL_INT(_debug, OID_AUTO, iosize_max_clamp, CTLFLAG_RW,
|
||||
&iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX");
|
||||
int devfs_iosize_max_clamp = 1;
|
||||
SYSCTL_INT(_debug, OID_AUTO, devfs_iosize_max_clamp, CTLFLAG_RW,
|
||||
&devfs_iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX for devices");
|
||||
|
||||
/*
|
||||
* Assert that the return value of read(2) and write(2) syscalls fits
|
||||
* into a register. If not, an architecture will need to provide the
|
||||
|
@ -623,29 +623,12 @@ sbappendrecord(struct sockbuf *sb, struct mbuf *m0)
|
||||
SOCKBUF_UNLOCK(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append address and data, and optionally, control (ancillary) data to the
|
||||
* receive queue of a socket. If present, m0 must include a packet header
|
||||
* with total length. Returns 0 if no space in sockbuf or insufficient
|
||||
* mbufs.
|
||||
*/
|
||||
int
|
||||
sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
struct mbuf *m0, struct mbuf *control)
|
||||
/* Helper routine that appends data, control, and address to a sockbuf. */
|
||||
static int
|
||||
sbappendaddr_locked_internal(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
struct mbuf *m0, struct mbuf *control, struct mbuf *ctrl_last)
|
||||
{
|
||||
struct mbuf *m, *n, *nlast;
|
||||
int space = asa->sa_len;
|
||||
|
||||
SOCKBUF_LOCK_ASSERT(sb);
|
||||
|
||||
if (m0 && (m0->m_flags & M_PKTHDR) == 0)
|
||||
panic("sbappendaddr_locked");
|
||||
if (m0)
|
||||
space += m0->m_pkthdr.len;
|
||||
space += m_length(control, &n);
|
||||
|
||||
if (space > sbspace(sb))
|
||||
return (0);
|
||||
#if MSIZE <= 256
|
||||
if (asa->sa_len > MLEN)
|
||||
return (0);
|
||||
@ -655,8 +638,8 @@ sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
return (0);
|
||||
m->m_len = asa->sa_len;
|
||||
bcopy(asa, mtod(m, caddr_t), asa->sa_len);
|
||||
if (n)
|
||||
n->m_next = m0; /* concatenate data to control */
|
||||
if (ctrl_last)
|
||||
ctrl_last->m_next = m0; /* concatenate data to control */
|
||||
else
|
||||
control = m0;
|
||||
m->m_next = control;
|
||||
@ -673,6 +656,50 @@ sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append address and data, and optionally, control (ancillary) data to the
|
||||
* receive queue of a socket. If present, m0 must include a packet header
|
||||
* with total length. Returns 0 if no space in sockbuf or insufficient
|
||||
* mbufs.
|
||||
*/
|
||||
int
|
||||
sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
struct mbuf *m0, struct mbuf *control)
|
||||
{
|
||||
struct mbuf *ctrl_last;
|
||||
int space = asa->sa_len;
|
||||
|
||||
SOCKBUF_LOCK_ASSERT(sb);
|
||||
|
||||
if (m0 && (m0->m_flags & M_PKTHDR) == 0)
|
||||
panic("sbappendaddr_locked");
|
||||
if (m0)
|
||||
space += m0->m_pkthdr.len;
|
||||
space += m_length(control, &ctrl_last);
|
||||
|
||||
if (space > sbspace(sb))
|
||||
return (0);
|
||||
return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last));
|
||||
}
|
||||
|
||||
/*
|
||||
* Append address and data, and optionally, control (ancillary) data to the
|
||||
* receive queue of a socket. If present, m0 must include a packet header
|
||||
* with total length. Returns 0 if insufficient mbufs. Does not validate space
|
||||
* on the receiving sockbuf.
|
||||
*/
|
||||
int
|
||||
sbappendaddr_nospacecheck_locked(struct sockbuf *sb, const struct sockaddr *asa,
|
||||
struct mbuf *m0, struct mbuf *control)
|
||||
{
|
||||
struct mbuf *ctrl_last;
|
||||
|
||||
SOCKBUF_LOCK_ASSERT(sb);
|
||||
|
||||
ctrl_last = (control == NULL) ? NULL : m_last(control);
|
||||
return (sbappendaddr_locked_internal(sb, asa, m0, control, ctrl_last));
|
||||
}
|
||||
|
||||
/*
|
||||
* Append address and data, and optionally, control (ancillary) data to the
|
||||
* receive queue of a socket. If present, m0 must include a packet header
|
||||
@ -1024,6 +1051,11 @@ sbcreatecontrol(caddr_t p, int size, int type, int level)
|
||||
m->m_len = 0;
|
||||
KASSERT(CMSG_SPACE((u_int)size) <= M_TRAILINGSPACE(m),
|
||||
("sbcreatecontrol: short mbuf"));
|
||||
/*
|
||||
* Don't leave the padding between the msg header and the
|
||||
* cmsg data and the padding after the cmsg data un-initialized.
|
||||
*/
|
||||
bzero(cp, CMSG_SPACE((u_int)size));
|
||||
if (p != NULL)
|
||||
(void)memcpy(CMSG_DATA(cp), p, size);
|
||||
m->m_len = CMSG_SPACE(size);
|
||||
|
@ -151,6 +151,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysent.h>
|
||||
#include <compat/freebsd32/freebsd32.h>
|
||||
#endif
|
||||
#ifdef __rtems__
|
||||
#include <rtems/libio.h>
|
||||
#define maxfiles rtems_libio_number_iops
|
||||
#endif /* __rtems__ */
|
||||
|
||||
static int soreceive_rcvoob(struct socket *so, struct uio *uio,
|
||||
int flags);
|
||||
@ -256,12 +260,14 @@ SYSCTL_NODE(_kern, KERN_IPC, ipc, CTLFLAG_RW, 0, "IPC");
|
||||
uma_zone_t socket_zone;
|
||||
int maxsockets;
|
||||
|
||||
#ifndef __rtems__
|
||||
static void
|
||||
socket_zone_change(void *tag)
|
||||
{
|
||||
|
||||
uma_zone_set_max(socket_zone, maxsockets);
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
|
||||
static void
|
||||
socket_init(void *tag)
|
||||
@ -270,8 +276,10 @@ socket_init(void *tag)
|
||||
socket_zone = uma_zcreate("socket", sizeof(struct socket), NULL, NULL,
|
||||
NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
|
||||
uma_zone_set_max(socket_zone, maxsockets);
|
||||
#ifndef __rtems__
|
||||
EVENTHANDLER_REGISTER(maxsockets_change, socket_zone_change, NULL,
|
||||
EVENTHANDLER_PRI_FIRST);
|
||||
#endif /* __rtems__ */
|
||||
}
|
||||
SYSINIT(socket, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, socket_init, NULL);
|
||||
|
||||
@ -284,11 +292,7 @@ init_maxsockets(void *ignored)
|
||||
{
|
||||
|
||||
TUNABLE_INT_FETCH("kern.ipc.maxsockets", &maxsockets);
|
||||
#ifndef __rtems__
|
||||
maxsockets = imax(maxsockets, imax(maxfiles, nmbclusters));
|
||||
#else /* __rtems__ */
|
||||
maxsockets = imax(maxsockets, nmbclusters);
|
||||
#endif /* __rtems__ */
|
||||
maxsockets = imax(maxsockets, maxfiles);
|
||||
}
|
||||
SYSINIT(param, SI_SUB_TUNABLES, SI_ORDER_ANY, init_maxsockets, NULL);
|
||||
|
||||
@ -304,15 +308,12 @@ sysctl_maxsockets(SYSCTL_HANDLER_ARGS)
|
||||
newmaxsockets = maxsockets;
|
||||
error = sysctl_handle_int(oidp, &newmaxsockets, 0, req);
|
||||
if (error == 0 && req->newptr) {
|
||||
if (newmaxsockets > maxsockets) {
|
||||
if (newmaxsockets > maxsockets &&
|
||||
newmaxsockets <= maxfiles) {
|
||||
maxsockets = newmaxsockets;
|
||||
#ifndef __rtems__
|
||||
if (maxsockets > ((maxfiles / 4) * 3)) {
|
||||
maxfiles = (maxsockets * 5) / 4;
|
||||
maxfilesperproc = (maxfiles * 9) / 10;
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
EVENTHANDLER_INVOKE(maxsockets_change);
|
||||
#endif /* __rtems__ */
|
||||
} else
|
||||
error = EINVAL;
|
||||
}
|
||||
@ -498,6 +499,10 @@ SYSCTL_INT(_regression, OID_AUTO, sonewconn_earlytest, CTLFLAG_RW,
|
||||
struct socket *
|
||||
sonewconn(struct socket *head, int connstatus)
|
||||
{
|
||||
static struct timeval lastover;
|
||||
static struct timeval overinterval = { 60, 0 };
|
||||
static int overcount;
|
||||
|
||||
struct socket *so;
|
||||
int over;
|
||||
|
||||
@ -509,9 +514,17 @@ sonewconn(struct socket *head, int connstatus)
|
||||
#else
|
||||
if (over) {
|
||||
#endif
|
||||
log(LOG_DEBUG, "%s: pcb %p: Listen queue overflow: "
|
||||
"%i already in queue awaiting acceptance\n",
|
||||
__func__, head->so_pcb, head->so_qlen);
|
||||
overcount++;
|
||||
|
||||
if (ratecheck(&lastover, &overinterval)) {
|
||||
log(LOG_DEBUG, "%s: pcb %p: Listen queue overflow: "
|
||||
"%i already in queue awaiting acceptance "
|
||||
"(%d occurrences)\n",
|
||||
__func__, head->so_pcb, head->so_qlen, overcount);
|
||||
|
||||
overcount = 0;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
VNET_ASSERT(head->so_vnet != NULL, ("%s:%d so_vnet is NULL, head=%p",
|
||||
@ -2679,22 +2692,12 @@ sosetopt(struct socket *so, struct sockopt *sopt)
|
||||
sizeof tv);
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
/* assert(hz > 0); */
|
||||
if (tv.tv_sec < 0 || tv.tv_sec > INT_MAX / hz ||
|
||||
tv.tv_usec < 0 || tv.tv_usec >= 1000000) {
|
||||
if (tv.tv_sec < 0 || tv.tv_usec < 0 ||
|
||||
tv.tv_usec >= 1000000) {
|
||||
error = EDOM;
|
||||
goto bad;
|
||||
}
|
||||
/* assert(tick > 0); */
|
||||
/* assert(ULONG_MAX - INT_MAX >= 1000000); */
|
||||
val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick;
|
||||
if (val > INT_MAX) {
|
||||
error = EDOM;
|
||||
goto bad;
|
||||
}
|
||||
if (val == 0 && tv.tv_usec != 0)
|
||||
val = 1;
|
||||
val = tvtohz(&tv);
|
||||
|
||||
switch (sopt->sopt_name) {
|
||||
case SO_SNDTIMEO:
|
||||
@ -3039,8 +3042,10 @@ void
|
||||
sohasoutofband(struct socket *so)
|
||||
{
|
||||
|
||||
#ifndef __rtems__
|
||||
if (so->so_sigio != NULL)
|
||||
pgsigio(&so->so_sigio, SIGURG, 0);
|
||||
#endif /* __rtems__ */
|
||||
selwakeuppri(&so->so_rcv.sb_sel, PSOCK);
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,13 @@ static int kern_getsockopt( struct thread *td, int s, int level, int name,
|
||||
void *val, enum uio_seg valseg, socklen_t *valsize);
|
||||
#endif /* __rtems__ */
|
||||
|
||||
/*
|
||||
* Creation flags, OR'ed into socket() and socketpair() type argument.
|
||||
* For stable/9, these are supported but not exposed in the header file.
|
||||
*/
|
||||
#define SOCK_CLOEXEC 0x10000000
|
||||
#define SOCK_NONBLOCK 0x20000000
|
||||
|
||||
static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
|
||||
static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
|
||||
|
||||
@ -239,11 +246,26 @@ sys_socket(td, uap)
|
||||
#endif /* __rtems__ */
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
int fd, error;
|
||||
int fd, error, type, oflag, fflag;
|
||||
|
||||
AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol);
|
||||
|
||||
type = uap->type;
|
||||
oflag = 0;
|
||||
fflag = 0;
|
||||
#ifndef __rtems__
|
||||
if ((type & SOCK_CLOEXEC) != 0) {
|
||||
type &= ~SOCK_CLOEXEC;
|
||||
oflag |= O_CLOEXEC;
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
if ((type & SOCK_NONBLOCK) != 0) {
|
||||
type &= ~SOCK_NONBLOCK;
|
||||
fflag |= FNONBLOCK;
|
||||
}
|
||||
|
||||
#ifdef MAC
|
||||
error = mac_socket_check_create(td->td_ucred, uap->domain, uap->type,
|
||||
error = mac_socket_check_create(td->td_ucred, uap->domain, type,
|
||||
uap->protocol);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -251,16 +273,18 @@ sys_socket(td, uap)
|
||||
#ifndef __rtems__
|
||||
fdp = td->td_proc->p_fd;
|
||||
#endif /* __rtems__ */
|
||||
error = falloc(td, &fp, &fd, 0);
|
||||
error = falloc(td, &fp, &fd, oflag);
|
||||
if (error)
|
||||
return (error);
|
||||
/* An extra reference on `fp' has been held for us by falloc(). */
|
||||
error = socreate(uap->domain, &so, uap->type, uap->protocol,
|
||||
error = socreate(uap->domain, &so, type, uap->protocol,
|
||||
td->td_ucred, td);
|
||||
if (error) {
|
||||
fdclose(fdp, fp, fd, td);
|
||||
} else {
|
||||
finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &socketops);
|
||||
finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops);
|
||||
if ((fflag & FNONBLOCK) != 0)
|
||||
(void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
|
||||
td->td_retval[0] = fd;
|
||||
}
|
||||
fdrop(fp, td);
|
||||
@ -798,9 +822,20 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
|
||||
struct filedesc *fdp = td->td_proc->p_fd;
|
||||
struct file *fp1, *fp2;
|
||||
struct socket *so1, *so2;
|
||||
int fd, error;
|
||||
int fd, error, oflag, fflag;
|
||||
|
||||
AUDIT_ARG_SOCKET(domain, type, protocol);
|
||||
|
||||
oflag = 0;
|
||||
fflag = 0;
|
||||
if ((type & SOCK_CLOEXEC) != 0) {
|
||||
type &= ~SOCK_CLOEXEC;
|
||||
oflag |= O_CLOEXEC;
|
||||
}
|
||||
if ((type & SOCK_NONBLOCK) != 0) {
|
||||
type &= ~SOCK_NONBLOCK;
|
||||
fflag |= FNONBLOCK;
|
||||
}
|
||||
#ifdef MAC
|
||||
/* We might want to have a separate check for socket pairs. */
|
||||
error = mac_socket_check_create(td->td_ucred, domain, type,
|
||||
@ -815,12 +850,12 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
|
||||
if (error)
|
||||
goto free1;
|
||||
/* On success extra reference to `fp1' and 'fp2' is set by falloc. */
|
||||
error = falloc(td, &fp1, &fd, 0);
|
||||
error = falloc(td, &fp1, &fd, oflag);
|
||||
if (error)
|
||||
goto free2;
|
||||
rsv[0] = fd;
|
||||
fp1->f_data = so1; /* so1 already has ref count */
|
||||
error = falloc(td, &fp2, &fd, 0);
|
||||
error = falloc(td, &fp2, &fd, oflag);
|
||||
if (error)
|
||||
goto free3;
|
||||
fp2->f_data = so2; /* so2 already has ref count */
|
||||
@ -836,8 +871,14 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
|
||||
if (error)
|
||||
goto free4;
|
||||
}
|
||||
finit(fp1, FREAD | FWRITE, DTYPE_SOCKET, fp1->f_data, &socketops);
|
||||
finit(fp2, FREAD | FWRITE, DTYPE_SOCKET, fp2->f_data, &socketops);
|
||||
finit(fp1, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp1->f_data,
|
||||
&socketops);
|
||||
finit(fp2, FREAD | FWRITE | fflag, DTYPE_SOCKET, fp2->f_data,
|
||||
&socketops);
|
||||
if ((fflag & FNONBLOCK) != 0) {
|
||||
(void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
|
||||
(void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
|
||||
}
|
||||
fdrop(fp1, td);
|
||||
fdrop(fp2, td);
|
||||
return (0);
|
||||
|
@ -339,6 +339,7 @@ static struct protosw localsw[] = {
|
||||
*/
|
||||
.pr_flags = PR_ADDR|PR_ATOMIC|PR_CONNREQUIRED|PR_WANTRCVD|
|
||||
PR_RIGHTS,
|
||||
.pr_ctloutput = &uipc_ctloutput,
|
||||
.pr_usrreqs = &uipc_usrreqs_seqpacket,
|
||||
},
|
||||
};
|
||||
@ -985,7 +986,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
from = &sun_noname;
|
||||
so2 = unp2->unp_socket;
|
||||
SOCKBUF_LOCK(&so2->so_rcv);
|
||||
if (sbappendaddr_locked(&so2->so_rcv, from, m, control)) {
|
||||
if (sbappendaddr_nospacecheck_locked(&so2->so_rcv, from, m,
|
||||
control)) {
|
||||
sorwakeup_locked(so2);
|
||||
m = NULL;
|
||||
control = NULL;
|
||||
@ -1047,7 +1049,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
if (unp2->unp_flags & UNP_WANTCRED) {
|
||||
#ifndef __rtems__
|
||||
/*
|
||||
* Credentials are passed only once on SOCK_STREAM.
|
||||
* Credentials are passed only once on SOCK_STREAM
|
||||
* and SOCK_SEQPACKET.
|
||||
*/
|
||||
unp2->unp_flags &= ~UNP_WANTCRED;
|
||||
control = unp_addsockcred(td, control);
|
||||
@ -1071,8 +1074,14 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
const struct sockaddr *from;
|
||||
|
||||
from = &sun_noname;
|
||||
if (sbappendaddr_locked(&so2->so_rcv, from, m,
|
||||
control))
|
||||
/*
|
||||
* Don't check for space available in so2->so_rcv.
|
||||
* Unix domain sockets only check for space in the
|
||||
* sending sockbuf, and that check is performed one
|
||||
* level up the stack.
|
||||
*/
|
||||
if (sbappendaddr_nospacecheck_locked(&so2->so_rcv,
|
||||
from, m, control))
|
||||
control = NULL;
|
||||
break;
|
||||
}
|
||||
@ -1495,7 +1504,7 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
}
|
||||
|
||||
/*
|
||||
* The connecter's (client's) credentials are copied from its
|
||||
* The connector's (client's) credentials are copied from its
|
||||
* process structure at the time of connect() (which is now).
|
||||
*/
|
||||
cru2x(td->td_ucred, &unp3->unp_peercred);
|
||||
|
@ -70,7 +70,7 @@ static __inline void
|
||||
mips_barrier(void)
|
||||
{
|
||||
#ifdef CPU_CNMIPS
|
||||
__asm __volatile("" : : : "memory");
|
||||
__compiler_membar();
|
||||
#else
|
||||
__asm __volatile (".set noreorder\n\t"
|
||||
"nop\n\t"
|
||||
|
@ -1030,8 +1030,45 @@ lacp_compose_key(struct lacp_port *lp)
|
||||
KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type"));
|
||||
KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface"));
|
||||
|
||||
/* bit 0..4: IFM_SUBTYPE */
|
||||
key = subtype;
|
||||
/* bit 0..4: IFM_SUBTYPE modulo speed */
|
||||
switch (subtype) {
|
||||
case IFM_10_T:
|
||||
case IFM_10_2:
|
||||
case IFM_10_5:
|
||||
case IFM_10_STP:
|
||||
case IFM_10_FL:
|
||||
key = IFM_10_T;
|
||||
break;
|
||||
case IFM_100_TX:
|
||||
case IFM_100_FX:
|
||||
case IFM_100_T4:
|
||||
case IFM_100_VG:
|
||||
case IFM_100_T2:
|
||||
key = IFM_100_TX;
|
||||
break;
|
||||
case IFM_1000_SX:
|
||||
case IFM_1000_LX:
|
||||
case IFM_1000_CX:
|
||||
case IFM_1000_T:
|
||||
key = IFM_1000_SX;
|
||||
break;
|
||||
case IFM_10G_LR:
|
||||
case IFM_10G_SR:
|
||||
case IFM_10G_CX4:
|
||||
case IFM_10G_TWINAX:
|
||||
case IFM_10G_TWINAX_LONG:
|
||||
case IFM_10G_LRM:
|
||||
case IFM_10G_T:
|
||||
key = IFM_10G_LR;
|
||||
break;
|
||||
case IFM_40G_CR4:
|
||||
case IFM_40G_SR4:
|
||||
case IFM_40G_LR4:
|
||||
key = IFM_40G_CR4;
|
||||
break;
|
||||
default:
|
||||
key = subtype;
|
||||
}
|
||||
/* bit 5..14: (some bits of) if_index of lagg device */
|
||||
key |= 0x7fe0 & ((sc->sc_ifp->if_index) << 5);
|
||||
/* bit 15: 0 */
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include <net/vnet.h>
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
@ -676,7 +677,8 @@ if_attach_internal(struct ifnet *ifp, int vmove)
|
||||
#if defined(INET) || defined(INET6)
|
||||
/* Initialize to max value. */
|
||||
if (ifp->if_hw_tsomax == 0)
|
||||
ifp->if_hw_tsomax = IP_MAXPACKET;
|
||||
ifp->if_hw_tsomax = min(IP_MAXPACKET, 32 * MCLBYTES -
|
||||
(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN));
|
||||
KASSERT(ifp->if_hw_tsomax <= IP_MAXPACKET &&
|
||||
ifp->if_hw_tsomax >= IP_MAXPACKET / 8,
|
||||
("%s: tsomax outside of range", __func__));
|
||||
|
@ -56,11 +56,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
#ifdef INET
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
@ -408,6 +408,11 @@ lagg_capabilities(struct lagg_softc *sc)
|
||||
struct lagg_port *lp;
|
||||
int cap = ~0, ena = ~0;
|
||||
u_long hwa = ~0UL;
|
||||
#if defined(INET) || defined(INET6)
|
||||
u_int hw_tsomax = IP_MAXPACKET; /* Initialize to the maximum value. */
|
||||
#else
|
||||
u_int hw_tsomax = ~0; /* if_hw_tsomax is only for INET/INET6, but.. */
|
||||
#endif
|
||||
|
||||
LAGG_WLOCK_ASSERT(sc);
|
||||
|
||||
@ -416,6 +421,10 @@ lagg_capabilities(struct lagg_softc *sc)
|
||||
cap &= lp->lp_ifp->if_capabilities;
|
||||
ena &= lp->lp_ifp->if_capenable;
|
||||
hwa &= lp->lp_ifp->if_hwassist;
|
||||
/* Set to the minimum value of the lagg ports. */
|
||||
if (lp->lp_ifp->if_hw_tsomax < hw_tsomax &&
|
||||
lp->lp_ifp->if_hw_tsomax > 0)
|
||||
hw_tsomax = lp->lp_ifp->if_hw_tsomax;
|
||||
}
|
||||
cap = (cap == ~0 ? 0 : cap);
|
||||
ena = (ena == ~0 ? 0 : ena);
|
||||
@ -423,10 +432,12 @@ lagg_capabilities(struct lagg_softc *sc)
|
||||
|
||||
if (sc->sc_ifp->if_capabilities != cap ||
|
||||
sc->sc_ifp->if_capenable != ena ||
|
||||
sc->sc_ifp->if_hwassist != hwa) {
|
||||
sc->sc_ifp->if_hwassist != hwa ||
|
||||
sc->sc_ifp->if_hw_tsomax != hw_tsomax) {
|
||||
sc->sc_ifp->if_capabilities = cap;
|
||||
sc->sc_ifp->if_capenable = ena;
|
||||
sc->sc_ifp->if_hwassist = hwa;
|
||||
sc->sc_ifp->if_hw_tsomax = hw_tsomax;
|
||||
getmicrotime(&sc->sc_ifp->if_lastchange);
|
||||
|
||||
if (sc->sc_ifflags & IFF_DEBUG)
|
||||
@ -822,7 +833,7 @@ lagg_port_output(struct ifnet *ifp, struct mbuf *m,
|
||||
|
||||
/* drop any other frames */
|
||||
m_freem(m);
|
||||
return (EBUSY);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1895,7 +1906,7 @@ lagg_lacp_start(struct lagg_softc *sc, struct mbuf *m)
|
||||
lp = lacp_select_tx_port(sc, m);
|
||||
if (lp == NULL) {
|
||||
m_freem(m);
|
||||
return (EBUSY);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
/* Send mbuf */
|
||||
|
@ -153,7 +153,10 @@ uint64_t ifmedia_baudrate(int);
|
||||
#define IFM_40G_CR4 27 /* 40GBase-CR4 */
|
||||
#define IFM_40G_SR4 28 /* 40GBase-SR4 */
|
||||
#define IFM_40G_LR4 29 /* 40GBase-LR4 */
|
||||
|
||||
/*
|
||||
* Please update ieee8023ad_lacp.c:lacp_compose_key()
|
||||
* after adding new Ethernet media types.
|
||||
*/
|
||||
/* note 31 is the max! */
|
||||
|
||||
#define IFM_ETH_MASTER 0x00000100 /* master mode (1000baseT) */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user