From owner-freebsd-hackers@FreeBSD.ORG Tue Jan 20 20:33:48 2009 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C35651065930 for ; Tue, 20 Jan 2009 20:33:48 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from harmony.bsdimp.com (bsdimp.com [199.45.160.85]) by mx1.freebsd.org (Postfix) with ESMTP id 6503C8FC08 for ; Tue, 20 Jan 2009 20:33:48 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from localhost (localhost [127.0.0.1]) by harmony.bsdimp.com (8.14.2/8.14.1) with ESMTP id n0KKUbrG003196; Tue, 20 Jan 2009 13:30:37 -0700 (MST) (envelope-from imp@bsdimp.com) Date: Tue, 20 Jan 2009 13:31:13 -0700 (MST) Message-Id: <20090120.133113.-1630673491.imp@bsdimp.com> To: gonzo@bluezbox.com From: "M. Warner Losh" In-Reply-To: <4976297C.7020405@bluezbox.com> References: <4976297C.7020405@bluezbox.com> X-Mailer: Mew version 5.2 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: freebsd-hackers@freebsd.org Subject: Re: uart and big-endian targets X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Jan 2009 20:33:49 -0000 In message: <4976297C.7020405@bluezbox.com> Oleksandr Tymoshenko writes: : Yesterday I ran into a "problem" with uart(4) on big-endian MIPS : board. uart code treats registers as bytes and reads/writes them using : bus_space_read_1/bus_space_write_1. To handle word-aligned registers we : have regshft in uart_bas structure. It works for little-endian flags : where lowest byte resides at uart_base + (regnum << regshft) address : but for big endian targets actual data resides at : uart_base + ((regnum + 1) << regshft) - 1. That's not the problem. The problem is that we're trying to do byte accesses to word registers. That's why we see a disconnect between the addresses since we're reading the wrong byte. also, we may be getting lucky with this access, but many chips have issues when you access word registers as bytes. : One way to solve it is to increase uart_base when setting uart_bas, : but it's not obvious and requires knowledge of uart(4) internals. : I think better solution would be to take into account endianess : when defining uart_regofs. Or if other BE devices have data in : highest byte new field should be added to uart_bas (defaulted to 0) : : Any thoughts? The base problem here is: uart.h: #define uart_getreg(bas, reg) \ bus_space_read_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) #define uart_setreg(bas, reg, value) \ bus_space_write_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value) These should be, for the platform you are using: #define uart_getreg(bas, reg) \ bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) #define uart_setreg(bas, reg, value) \ bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value) There's no easy way to swap these out, nor is there a way to have variants for different kinds of hardware attached to the same machine (the UART on the SoC will have different access patterns than the UART on the modem on the PC Card that's plugged in, for example). This is a short-coming in the design of UART. One that's relatively easy to fix, mind you, and one that could easily be fixed. There's so many twists like this that it can be hard to anticipate them all. The Octeon port basically copies uart_dev_ns8250.c and provides its own set of accessors. This is right from a accessing the hardware correctly point of view, but a pita from a code reuse point of view. Were it not for the other quirks in Cavium's serial ports, there'd be little reason to go this route... Warner