mirror of
https://github.com/opnsense/src.git
synced 2026-06-06 07:12:52 -04:00
Remove SOC FPGA drivers
The drivers have been disconnected from the build since the removal of the SOCFPGA kernel configs. Reviewed by: manu, imp, andrew Sponsored by: AFRL, DARPA Differential Revision: https://reviews.freebsd.org/D47885
This commit is contained in:
parent
e248e08a15
commit
8f7835acc6
57 changed files with 8 additions and 13332 deletions
|
|
@ -51,6 +51,14 @@
|
|||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 2024xxxx: Remove Altera DE4 drivers
|
||||
OLD_FILES+=usr/share/man/man4/altera_atse.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/altera_avgen.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/altera_jtag_uart.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/altera_sdcard.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/altera_sdcardc.4.gz
|
||||
OLD_FILES+=usr/share/man/man4/atse.4.gz
|
||||
|
||||
# 20241124: library and tests of OpenBSD dc
|
||||
OLD_FILES+=usr/share/misc/bc.library
|
||||
OLD_FILES+=usr/tests/usr.bin/dc/Kyuafile
|
||||
|
|
|
|||
|
|
@ -38,10 +38,6 @@ MAN= aac.4 \
|
|||
alc.4 \
|
||||
ale.4 \
|
||||
alpm.4 \
|
||||
altera_atse.4 \
|
||||
altera_avgen.4 \
|
||||
altera_jtag_uart.4 \
|
||||
altera_sdcard.4 \
|
||||
altq.4 \
|
||||
amdpm.4 \
|
||||
${_amdsbwd.4} \
|
||||
|
|
@ -651,8 +647,6 @@ MLINKS+=age.4 if_age.4
|
|||
MLINKS+=agp.4 agpgart.4
|
||||
MLINKS+=alc.4 if_alc.4
|
||||
MLINKS+=ale.4 if_ale.4
|
||||
MLINKS+=altera_atse.4 atse.4
|
||||
MLINKS+=altera_sdcard.4 altera_sdcardc.4
|
||||
MLINKS+=altq.4 ALTQ.4
|
||||
MLINKS+=ath.4 if_ath.4
|
||||
MLINKS+=aue.4 if_aue.4
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
.\"-
|
||||
.\" Copyright (c) 2013-2014 SRI International
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This software was developed by SRI International and the University of
|
||||
.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
.\" ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd May 21, 2014
|
||||
.Dt ALTERA_ATSE 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm atse
|
||||
.Nd driver for the Altera Triple-Speed Ethernet MegaCore
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device atse"
|
||||
.Cd "options ATSE_CFI_HACK"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.atse.0.at="nexus0"
|
||||
.Cd hint.atse.0.maddr=0x7f007000
|
||||
.Cd hint.atse.0.msize=0x540
|
||||
.Cd hint.atse.0.rc_irq=1
|
||||
.Cd hint.atse.0.rx_maddr=0x7f007500
|
||||
.Cd hint.atse.0.rx_msize=0x8
|
||||
.Cd hint.atse.0.rxc_maddr=0x7f007520
|
||||
.Cd hint.atse.0.rxc_msize=0x20
|
||||
.Cd hint.atse.0.tx_irq=2
|
||||
.Cd hint.atse.0.tx_maddr=0x7f007400
|
||||
.Cd hint.atse.0.tx_msize=0x8
|
||||
.Cd hint.atse.0.txc_maddr=0x7f007420
|
||||
.Cd hint.atse.0.txc_msize=0x20
|
||||
.Cd hint.e1000phy.0.at="miibus0"
|
||||
.Cd hint.e1000phy.0.phyno=0
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
device driver provides support for the Altera Triple-Speed Ethernet
|
||||
MegaCore.
|
||||
.Sh HARDWARE
|
||||
The current version of the
|
||||
.Nm
|
||||
driver supports the Ethernet MegaCore as described in version 11.1 of
|
||||
Altera's documentation when the device is configured with internal FIFOs.
|
||||
.Sh MAC SELECTION
|
||||
The default MAC address for each
|
||||
.Nm
|
||||
interface is derived from a value stored in
|
||||
.Xr cfi 4
|
||||
flash.
|
||||
The value is managed by the
|
||||
.Xr atsectl 8
|
||||
utility.
|
||||
.Pp
|
||||
Only a single MAC address may be stored in flash.
|
||||
If the address begins with the Altera prefix 00:07:ed and ends in 00 then
|
||||
up to 16 addresses will be derived from it by adding the unit number of
|
||||
the interface to the stored address.
|
||||
For other prefixes, the address will be assigned to atse0 and random
|
||||
addresses will be used for other interfaces.
|
||||
If the stored address is invalid, for example all zero's, multicast, or the
|
||||
default address shipped on all DE4 boards (00:07:ed:ff:ed:15) then a random
|
||||
address is generated when the device is attached.
|
||||
.Sh SEE ALSO
|
||||
.Xr miibus 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr ifconfig 8
|
||||
.Rs
|
||||
.%T Triple-Speed Ethernet MegaCore Function User Guide
|
||||
.%D November 2011
|
||||
.%I Altera Corporation
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device driver first appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were
|
||||
developed by SRI International and the University of Cambridge Computer
|
||||
Laboratory under DARPA/AFRL contract
|
||||
.Pq FA8750-10-C-0237
|
||||
.Pq Do CTSRD Dc ,
|
||||
as part of the DARPA CRASH research programme.
|
||||
This device driver was written by
|
||||
.An Bjoern A. Zeeb .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Nm
|
||||
driver only supports a single configuration of the MegaCore as installed
|
||||
on the Terasic Technologies Altera DE4 Development and Education Board.
|
||||
.Pp
|
||||
Only gigabit Ethernet speeds are currently supported.
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
.\"-
|
||||
.\" Copyright (c) 2012 Robert N. M. Watson
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This software was developed by SRI International and the University of
|
||||
.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
.\" ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 18, 2012
|
||||
.Dt ALTERA_AVGEN 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm altera_avgen
|
||||
.Nd driver for generic Altera Avalon-bus-attached, memory-mapped devices
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device altera_avgen"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.altera_avgen.0.at="nexus0"
|
||||
.Cd hint.altera_avgen.0.maddr=0x7f00a000
|
||||
.Cd hint.altera_avgen.0.msize=20
|
||||
.Cd hint.altera_avgen.0.width=4
|
||||
.Cd hint.altera_avgen.0.fileio="rw"
|
||||
.Cd hint.altera_avgen.0.devname="berirom"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
device driver provides generic support for memory-mapped devices on the
|
||||
Altera Avalon bus.
|
||||
.Pa device.hints
|
||||
entries configure the address, size, I/O disposition, and
|
||||
.Pa /dev
|
||||
device node name that will be used.
|
||||
The
|
||||
.Xr open 2 ,
|
||||
.Xr read 2 ,
|
||||
.Xr write 2 ,
|
||||
and
|
||||
.Xr mmap 2
|
||||
system calls (and variations) may be used on
|
||||
.Nm
|
||||
device nodes, subject to constraints imposed using
|
||||
.Pa device.hints
|
||||
entries.
|
||||
Although reading and writing mapped memory is supported,
|
||||
.Nm
|
||||
does not currently support directing device interrupts to userspace.
|
||||
.Pp
|
||||
A number of
|
||||
.Pa device.hints
|
||||
sub-fields are available to configure
|
||||
.Nm
|
||||
device instances:
|
||||
.Bl -tag -width devunit
|
||||
.It maddr
|
||||
base physical address of the memory region to export; must be aligned to
|
||||
.Li width
|
||||
.It msize
|
||||
length of the memory region export; must be aligned to
|
||||
.Li width
|
||||
.It width
|
||||
Granularity at which
|
||||
.Xr read 2
|
||||
and
|
||||
.Xr write 2
|
||||
operations will be performed.
|
||||
Larger requests will be broken down into
|
||||
.Li width -sized
|
||||
operations; smaller requests will be rejected.
|
||||
I/O operations must be aligned to
|
||||
.Li width .
|
||||
.It fileio
|
||||
allowed file descriptor operations;
|
||||
.Li r
|
||||
authorizes
|
||||
.Xr read 2 ;
|
||||
.Li w
|
||||
authorizes
|
||||
.Xr write 2 .
|
||||
.It mmapio
|
||||
allowed
|
||||
.Xr mmap 2
|
||||
permissions;
|
||||
.Li w
|
||||
authorizes
|
||||
.Dv PROT_WRITE ;
|
||||
.Li r
|
||||
authorizes
|
||||
.Dv PROT_READ ;
|
||||
.Li x
|
||||
authorizes
|
||||
.Dv PROT_EXEC .
|
||||
.It devname
|
||||
specifies a device name relative to
|
||||
.Pa /dev .
|
||||
.It devunit
|
||||
specifies a device unit number; no unit number is used if this is unspecified.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mmap 2 ,
|
||||
.Xr open 2 ,
|
||||
.Xr read 2 ,
|
||||
.Xr write 2
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device driver first appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were
|
||||
developed by SRI International and the University of Cambridge Computer
|
||||
Laboratory under DARPA/AFRL contract
|
||||
.Pq FA8750-10-C-0237
|
||||
.Pq Do CTSRD Dc ,
|
||||
as part of the DARPA CRASH research programme.
|
||||
This device driver was written by
|
||||
.An Robert N. M. Watson .
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
is intended to support the writing of userspace device drivers; however, it
|
||||
does not permit directing interrupts to userspace, only memory-mapped I/O.
|
||||
.Pp
|
||||
.Nm
|
||||
supports only a
|
||||
.Li nexus
|
||||
bus attachment, which is appropriate for system-on-chip busses such as
|
||||
Altera's Avalon bus.
|
||||
If the target device is off of another bus type, then additional bus
|
||||
attachments will be required.
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
.\"-
|
||||
.\" Copyright (c) 2012 Robert N. M. Watson
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This software was developed by SRI International and the University of
|
||||
.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
.\" ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 18, 2012
|
||||
.Dt ALTERA_JTAG_UART 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm altera_jtag_uart
|
||||
.Nd driver for the Altera JTAG UART Core
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device altera_jtag_uart"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.altera_jtag_uart.0.at="nexus0"
|
||||
.Cd hint.altera_jtag_uart.0.maddr=0x7f000000
|
||||
.Cd hint.altera_jtag_uart.0.msize=0x40
|
||||
.Cd hint.altera_jtag_uart.0.irq=0
|
||||
.Cd hint.altera_jtag_uart.1.at="nexus0"
|
||||
.Cd hint.altera_jtag_uart.1.maddr=0x7f001000
|
||||
.Cd hint.altera_jtag_uart.1.msize=0x40
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
device driver provides support for the Altera JTAG UART core, which allows
|
||||
multiple UART-like streams to be carried over JTAG.
|
||||
.Nm
|
||||
allows JTAG UART streams to be attached to both the low-level console
|
||||
interface, used for direct kernel input and output, and the
|
||||
.Xr tty 4
|
||||
layer, to be used with
|
||||
.Xr ttys 5
|
||||
and
|
||||
.Xr login 1 .
|
||||
Sequential Altera JTAG UART devices will appear as
|
||||
.Li ttyu0 ,
|
||||
.Li ttyu1 ,
|
||||
etc.
|
||||
.Sh HARDWARE
|
||||
Altera JTAG UART devices can be connected to using Altera's
|
||||
.Pa nios2-terminal
|
||||
program, with the instance selected using the
|
||||
.Li --instance
|
||||
argument on the management host.
|
||||
.Nm
|
||||
supports JTAG UART cores with or without interrupt lines connected; if the
|
||||
.Li irq
|
||||
portion of the
|
||||
.Pa device.hints
|
||||
entry is omitted, the driver will poll rather than configure interrupts.
|
||||
.Sh SEE ALSO
|
||||
.Xr login 1 ,
|
||||
.Xr tty 4 ,
|
||||
.Xr ttys 5
|
||||
.Rs
|
||||
.%T Altera Embedded Peripherals IP User Guide
|
||||
.%D June 2011
|
||||
.%I Altera Corporation
|
||||
.%U http://www.altera.com/literature/ug/ug_embedded_ip.pdf
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device driver first appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were
|
||||
developed by SRI International and the University of Cambridge Computer
|
||||
Laboratory under DARPA/AFRL contract
|
||||
.Pq FA8750-10-C-0237
|
||||
.Pq Do CTSRD Dc ,
|
||||
as part of the DARPA CRASH research programme.
|
||||
This device driver was written by
|
||||
.An Robert N. M. Watson .
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
must dynamically poll to detect when JTAG is present, in order to disable flow
|
||||
control in the event that there is no receiving endpoint.
|
||||
Otherwise, the boot may hang waiting for the JTAG client to be attached, and
|
||||
user processes attached to JTAG UART devices might block indefinitely.
|
||||
However, there is no way to flush the output buffer once JTAG is detected to
|
||||
have disappeared; this means that a small amount of stale output data will
|
||||
remain in the output buffer, being displayed by
|
||||
.Li nios2-terminal
|
||||
when it is connected.
|
||||
Loss of JTAG will not generate a hang-up event, as that is rarely the desired
|
||||
behaviour.
|
||||
.Pp
|
||||
.Li nios2-terminal
|
||||
does not place the client-side TTY in raw mode, and so by default will not
|
||||
pass all control characters through to the UART.
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
.\"-
|
||||
.\" Copyright (c) 2012 Robert N. M. Watson
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This software was developed by SRI International and the University of
|
||||
.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
.\" ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 18, 2012
|
||||
.Dt ALTERA_SDCARD 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm altera_sdcard
|
||||
.Nd driver for the Altera University Program Secure Data Card IP Core
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device altera_sdcard"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.altera_sdcardc.0.at="nexus0"
|
||||
.Cd hint.altera_sdcardc.0.maddr=0x7f008000
|
||||
.Cd hint.altera_sdcardc.0.msize=0x400
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
device driver provides support for the Altera University Program Secure Data
|
||||
Card (SD Card) IP Core device.
|
||||
A controller device,
|
||||
.Li altera_sdcardcX ,
|
||||
will be attached during boot.
|
||||
Inserted disks are presented as
|
||||
.Xr disk 9
|
||||
devices,
|
||||
.Li altera_sdcardX ,
|
||||
corresponding to the controller number.
|
||||
.Sh HARDWARE
|
||||
The current version of the
|
||||
.Nm
|
||||
driver supports the SD Card IP core as described in the August 2011 version of
|
||||
Altera's documentation.
|
||||
The core supports only cards up to 2G (CSD 0); larger cards, or cards using
|
||||
newer CSD versions, will not be detected.
|
||||
The IP core has two key limitations: a lack of interrupt support, requiring
|
||||
timer-driven polling to detect I/O completion, and support for only single
|
||||
512-byte block read and write operations at a time.
|
||||
The combined effect of those two limits is that the system clock rate,
|
||||
.Dv HZ ,
|
||||
must be set to at least 200 in order to accomplish the maximum 100KB/s data
|
||||
rate supported by the IP core.
|
||||
.Sh SEE ALSO
|
||||
.Xr disk 9
|
||||
.Rs
|
||||
.%T Altera University Program Secure Data Card IP Core
|
||||
.%D August 2011
|
||||
.%I Altera Corporation - University Program
|
||||
.%U ftp://ftp.altera.com/up/pub/Altera_Material/11.0/University_Program_IP_Cores/Memory/SD_Card_Interface_for_SoPC_Builder.pdf
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
device driver first appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver and this manual page were
|
||||
developed by SRI International and the University of Cambridge Computer
|
||||
Laboratory under DARPA/AFRL contract
|
||||
.Pq FA8750-10-C-0237
|
||||
.Pq Do CTSRD Dc ,
|
||||
as part of the DARPA CRASH research programme.
|
||||
This device driver was written by
|
||||
.An Robert N. M. Watson .
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
contains a number of work-arounds for IP core bugs.
|
||||
Perhaps most critically,
|
||||
.Nm
|
||||
ignores the CRC error bit returned in the RR1 register, which appears to be
|
||||
unexpectedly set by the IP core.
|
||||
.Pp
|
||||
.Nm
|
||||
uses fixed polling intervals are used for card insertion/removal and
|
||||
I/O completion detection; an adaptive strategy might improve performance by
|
||||
reducing the latency to detecting completed I/O.
|
||||
However, in our experiments, using polling rates greater than 200 times a
|
||||
second did not improve performance.
|
||||
.Pp
|
||||
.Nm
|
||||
supports only a
|
||||
.Li nexus
|
||||
bus attachment, which is appropriate for system-on-chip busses such as
|
||||
Altera's Avalon bus.
|
||||
If the IP core is configured off of another bus type, then additional bus
|
||||
attachments will be required.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
arm/altera/socfpga/socfpga_common.c standard
|
||||
arm/altera/socfpga/socfpga_machdep.c standard
|
||||
arm/altera/socfpga/socfpga_manager.c standard
|
||||
arm/altera/socfpga/socfpga_rstmgr.c standard
|
||||
arm/altera/socfpga/socfpga_mp.c optional smp
|
||||
|
||||
dev/mmc/host/dwmmc_altera.c optional dwmmc
|
||||
|
||||
# Arria 10
|
||||
arm/altera/socfpga/socfpga_a10_manager.c standard
|
||||
|
||||
# BERI specific
|
||||
dev/beri/beri_ring.c optional beri_ring
|
||||
dev/beri/beri_mem.c optional beri_mem
|
||||
dev/beri/virtio/virtio.c optional beri_vtblk | vtbe
|
||||
dev/beri/virtio/virtio_block.c optional beri_vtblk
|
||||
dev/beri/virtio/network/if_vtbe.c optional vtbe
|
||||
|
|
@ -1,437 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Intel Arria 10 FPGA Manager.
|
||||
* Chapter 4, Arria 10 Hard Processor System Technical Reference Manual.
|
||||
* Chapter A, FPGA Reconfiguration.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_common.h>
|
||||
|
||||
#define FPGAMGR_DCLKCNT 0x8 /* DCLK Count Register */
|
||||
#define FPGAMGR_DCLKSTAT 0xC /* DCLK Status Register */
|
||||
#define FPGAMGR_GPO 0x10 /* General-Purpose Output Register */
|
||||
#define FPGAMGR_GPI 0x14 /* General-Purpose Input Register */
|
||||
#define FPGAMGR_MISCI 0x18 /* Miscellaneous Input Register */
|
||||
#define IMGCFG_CTRL_00 0x70
|
||||
#define S2F_CONDONE_OE (1 << 24)
|
||||
#define S2F_NSTATUS_OE (1 << 16)
|
||||
#define CTRL_00_NCONFIG (1 << 8)
|
||||
#define CTRL_00_NENABLE_CONDONE (1 << 2)
|
||||
#define CTRL_00_NENABLE_NSTATUS (1 << 1)
|
||||
#define CTRL_00_NENABLE_NCONFIG (1 << 0)
|
||||
#define IMGCFG_CTRL_01 0x74
|
||||
#define CTRL_01_S2F_NCE (1 << 24)
|
||||
#define CTRL_01_S2F_PR_REQUEST (1 << 16)
|
||||
#define CTRL_01_S2F_NENABLE_CONFIG (1 << 0)
|
||||
#define IMGCFG_CTRL_02 0x78
|
||||
#define CTRL_02_CDRATIO_S 16
|
||||
#define CTRL_02_CDRATIO_M (0x3 << CTRL_02_CDRATIO_S)
|
||||
#define CTRL_02_CFGWIDTH_16 (0 << 24)
|
||||
#define CTRL_02_CFGWIDTH_32 (1 << 24)
|
||||
#define CTRL_02_EN_CFG_DATA (1 << 8)
|
||||
#define CTRL_02_EN_CFG_CTRL (1 << 0)
|
||||
#define IMGCFG_STAT 0x80
|
||||
#define F2S_PR_ERROR (1 << 11)
|
||||
#define F2S_PR_DONE (1 << 10)
|
||||
#define F2S_PR_READY (1 << 9)
|
||||
#define F2S_MSEL_S 16
|
||||
#define F2S_MSEL_M (0x7 << F2S_MSEL_S)
|
||||
#define MSEL_PASSIVE_FAST 0
|
||||
#define MSEL_PASSIVE_SLOW 1
|
||||
#define F2S_NCONFIG_PIN (1 << 12)
|
||||
#define F2S_CONDONE_OE (1 << 7)
|
||||
#define F2S_NSTATUS_PIN (1 << 4)
|
||||
#define F2S_CONDONE_PIN (1 << 6)
|
||||
#define F2S_USERMODE (1 << 2)
|
||||
|
||||
struct fpgamgr_a10_softc {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst_data;
|
||||
bus_space_handle_t bsh_data;
|
||||
struct cdev *mgr_cdev;
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
static struct resource_spec fpgamgr_a10_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
fpga_wait_dclk_pulses(struct fpgamgr_a10_softc *sc, int npulses)
|
||||
{
|
||||
int tout;
|
||||
|
||||
/* Clear done bit, if any */
|
||||
if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
|
||||
WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
|
||||
|
||||
/* Request DCLK pulses */
|
||||
WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
|
||||
|
||||
/* Wait finish */
|
||||
tout = 1000;
|
||||
while (tout > 0) {
|
||||
if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
|
||||
WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
|
||||
break;
|
||||
}
|
||||
tout--;
|
||||
DELAY(10);
|
||||
}
|
||||
if (tout == 0) {
|
||||
device_printf(sc->dev,
|
||||
"Error: dclkpulses wait timeout\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_open(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct fpgamgr_a10_softc *sc;
|
||||
int tout;
|
||||
int msel;
|
||||
int reg;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/* Step 1 */
|
||||
reg = READ4(sc, IMGCFG_STAT);
|
||||
if ((reg & F2S_USERMODE) == 0) {
|
||||
device_printf(sc->dev, "Error: invalid mode\n");
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
/* Step 2 */
|
||||
reg = READ4(sc, IMGCFG_STAT);
|
||||
msel = (reg & F2S_MSEL_M) >> F2S_MSEL_S;
|
||||
if ((msel != MSEL_PASSIVE_FAST) && \
|
||||
(msel != MSEL_PASSIVE_SLOW)) {
|
||||
device_printf(sc->dev,
|
||||
"Error: invalid msel %d\n", msel);
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
/*
|
||||
* Step 3.
|
||||
* TODO: add support for compressed, encrypted images.
|
||||
*/
|
||||
reg = READ4(sc, IMGCFG_CTRL_02);
|
||||
reg &= ~(CTRL_02_CDRATIO_M);
|
||||
WRITE4(sc, IMGCFG_CTRL_02, reg);
|
||||
|
||||
reg = READ4(sc, IMGCFG_CTRL_02);
|
||||
reg &= ~CTRL_02_CFGWIDTH_32;
|
||||
WRITE4(sc, IMGCFG_CTRL_02, reg);
|
||||
|
||||
/* Step 4. a */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg &= ~CTRL_01_S2F_PR_REQUEST;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
reg = READ4(sc, IMGCFG_CTRL_00);
|
||||
reg |= CTRL_00_NCONFIG;
|
||||
WRITE4(sc, IMGCFG_CTRL_00, reg);
|
||||
|
||||
/* b */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg &= ~CTRL_01_S2F_NCE;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* c */
|
||||
reg = READ4(sc, IMGCFG_CTRL_02);
|
||||
reg |= CTRL_02_EN_CFG_CTRL;
|
||||
WRITE4(sc, IMGCFG_CTRL_02, reg);
|
||||
|
||||
/* d */
|
||||
reg = READ4(sc, IMGCFG_CTRL_00);
|
||||
reg &= ~S2F_CONDONE_OE;
|
||||
reg &= ~S2F_NSTATUS_OE;
|
||||
reg |= CTRL_00_NCONFIG;
|
||||
reg |= CTRL_00_NENABLE_NSTATUS;
|
||||
reg |= CTRL_00_NENABLE_CONDONE;
|
||||
reg &= ~CTRL_00_NENABLE_NCONFIG;
|
||||
WRITE4(sc, IMGCFG_CTRL_00, reg);
|
||||
|
||||
/* Step 5 */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg &= ~CTRL_01_S2F_NENABLE_CONFIG;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* Step 6 */
|
||||
fpga_wait_dclk_pulses(sc, 0x100);
|
||||
|
||||
/* Step 7. a */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg |= CTRL_01_S2F_PR_REQUEST;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* b, c */
|
||||
fpga_wait_dclk_pulses(sc, 0x7ff);
|
||||
|
||||
/* Step 8 */
|
||||
tout = 10;
|
||||
while (tout--) {
|
||||
reg = READ4(sc, IMGCFG_STAT);
|
||||
if (reg & F2S_PR_ERROR) {
|
||||
device_printf(sc->dev,
|
||||
"Error: PR failed on open.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (reg & F2S_PR_READY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tout == 0) {
|
||||
device_printf(sc->dev,
|
||||
"Error: Timeout waiting PR ready bit.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_close(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct fpgamgr_a10_softc *sc;
|
||||
int tout;
|
||||
int reg;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/* Step 10 */
|
||||
tout = 10;
|
||||
while (tout--) {
|
||||
reg = READ4(sc, IMGCFG_STAT);
|
||||
if (reg & F2S_PR_ERROR) {
|
||||
device_printf(sc->dev,
|
||||
"Error: PR failed.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (reg & F2S_PR_DONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 11 */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg &= ~CTRL_01_S2F_PR_REQUEST;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* Step 12, 13 */
|
||||
fpga_wait_dclk_pulses(sc, 0x100);
|
||||
|
||||
/* Step 14 */
|
||||
reg = READ4(sc, IMGCFG_CTRL_02);
|
||||
reg &= ~CTRL_02_EN_CFG_CTRL;
|
||||
WRITE4(sc, IMGCFG_CTRL_02, reg);
|
||||
|
||||
/* Step 15 */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg |= CTRL_01_S2F_NCE;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* Step 16 */
|
||||
reg = READ4(sc, IMGCFG_CTRL_01);
|
||||
reg |= CTRL_01_S2F_NENABLE_CONFIG;
|
||||
WRITE4(sc, IMGCFG_CTRL_01, reg);
|
||||
|
||||
/* Step 17 */
|
||||
reg = READ4(sc, IMGCFG_STAT);
|
||||
if ((reg & F2S_USERMODE) == 0) {
|
||||
device_printf(sc->dev,
|
||||
"Error: invalid mode\n");
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
if ((reg & F2S_CONDONE_PIN) == 0) {
|
||||
device_printf(sc->dev,
|
||||
"Error: configuration not done\n");
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
if ((reg & F2S_NSTATUS_PIN) == 0) {
|
||||
device_printf(sc->dev,
|
||||
"Error: nstatus pin\n");
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct fpgamgr_a10_softc *sc;
|
||||
uint32_t buffer;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/*
|
||||
* Step 9.
|
||||
* Device supports 4-byte writes only.
|
||||
*/
|
||||
|
||||
while (uio->uio_resid >= 4) {
|
||||
uiomove(&buffer, 4, uio);
|
||||
bus_space_write_4(sc->bst_data, sc->bsh_data,
|
||||
0x0, buffer);
|
||||
}
|
||||
|
||||
switch (uio->uio_resid) {
|
||||
case 3:
|
||||
uiomove(&buffer, 3, uio);
|
||||
buffer &= 0xffffff;
|
||||
bus_space_write_4(sc->bst_data, sc->bsh_data,
|
||||
0x0, buffer);
|
||||
break;
|
||||
case 2:
|
||||
uiomove(&buffer, 2, uio);
|
||||
buffer &= 0xffff;
|
||||
bus_space_write_4(sc->bst_data, sc->bsh_data,
|
||||
0x0, buffer);
|
||||
break;
|
||||
case 1:
|
||||
uiomove(&buffer, 1, uio);
|
||||
buffer &= 0xff;
|
||||
bus_space_write_4(sc->bst_data, sc->bsh_data,
|
||||
0x0, buffer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cdevsw fpga_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = fpga_open,
|
||||
.d_close = fpga_close,
|
||||
.d_write = fpga_write,
|
||||
.d_ioctl = fpga_ioctl,
|
||||
.d_name = "FPGA Manager",
|
||||
};
|
||||
|
||||
static int
|
||||
fpgamgr_a10_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,socfpga-a10-fpga-mgr"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Arria 10 FPGA Manager");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
fpgamgr_a10_attach(device_t dev)
|
||||
{
|
||||
struct fpgamgr_a10_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, fpgamgr_a10_spec, sc->res)) {
|
||||
device_printf(dev, "Could not allocate resources.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst_data = rman_get_bustag(sc->res[1]);
|
||||
sc->bsh_data = rman_get_bushandle(sc->res[1]);
|
||||
|
||||
sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
0600, "fpga%d", device_get_unit(sc->dev));
|
||||
|
||||
if (sc->mgr_cdev == NULL) {
|
||||
device_printf(dev, "Failed to create character device.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->mgr_cdev->si_drv1 = sc;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t fpgamgr_a10_methods[] = {
|
||||
DEVMETHOD(device_probe, fpgamgr_a10_probe),
|
||||
DEVMETHOD(device_attach, fpgamgr_a10_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t fpgamgr_a10_driver = {
|
||||
"fpgamgr_a10",
|
||||
fpgamgr_a10_methods,
|
||||
sizeof(struct fpgamgr_a10_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(fpgamgr_a10, simplebus, fpgamgr_a10_driver, 0, 0);
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_rstmgr.h>
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define READ4(_sc, _reg) bus_read_4((_sc)->res[0], _reg)
|
||||
#define READ2(_sc, _reg) bus_read_2((_sc)->res[0], _reg)
|
||||
#define READ1(_sc, _reg) bus_read_1((_sc)->res[0], _reg)
|
||||
#define WRITE4(_sc, _reg, _val) bus_write_4((_sc)->res[0], _reg, _val)
|
||||
#define WRITE2(_sc, _reg, _val) bus_write_2((_sc)->res[0], _reg, _val)
|
||||
#define WRITE1(_sc, _reg, _val) bus_write_1((_sc)->res[0], _reg, _val)
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define L3REGS_REMAP 0x0 /* Remap */
|
||||
#define REMAP_LWHPS2FPGA (1 << 4)
|
||||
#define REMAP_HPS2FPGA (1 << 3)
|
||||
#define REMAP_MPUZERO (1 << 0)
|
||||
#define L3REGS_L4MAIN 0x8 /* L4 main peripherals security */
|
||||
#define L3REGS_L4SP 0xC /* L4 SP Peripherals Security */
|
||||
#define L3REGS_L4MP 0x10 /* L4 MP Peripherals Security */
|
||||
#define L3REGS_L4OSC1 0x14 /* L4 OSC1 Peripherals Security */
|
||||
#define L3REGS_L4SPIM 0x18 /* L4 SPIM Peripherals Security */
|
||||
#define L3REGS_STM 0x1C /* STM Peripheral Security */
|
||||
#define L3REGS_LWHPS2FPGAREGS 0x20 /* LWHPS2FPGA AXI Bridge Security */
|
||||
#define L3REGS_USB1 0x28 /* USB1 Peripheral Security */
|
||||
#define L3REGS_NANDDATA 0x2C /* NAND Flash Controller Data Sec */
|
||||
#define L3REGS_USB0 0x80 /* USB0 Peripheral Security */
|
||||
#define L3REGS_NANDREGS 0x84 /* NAND Flash Controller Security */
|
||||
#define L3REGS_QSPIDATA 0x88 /* QSPI Flash Controller Data Sec */
|
||||
#define L3REGS_FPGAMGRDATA 0x8C /* FPGA Manager Data Peripheral Sec */
|
||||
#define L3REGS_HPS2FPGAREGS 0x90 /* HPS2FPGA AXI Bridge Perip. Sec */
|
||||
#define L3REGS_ACP 0x94 /* MPU ACP Peripheral Security */
|
||||
#define L3REGS_ROM 0x98 /* ROM Peripheral Security */
|
||||
#define L3REGS_OCRAM 0x9C /* On-chip RAM Peripheral Security */
|
||||
#define L3REGS_SDRDATA 0xA0 /* SDRAM Data Peripheral Security */
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_platform.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/devmap.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/armreg.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/machdep.h>
|
||||
#include <machine/platform.h>
|
||||
#include <machine/platformvar.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_mp.h>
|
||||
#include <arm/altera/socfpga/socfpga_rstmgr.h>
|
||||
|
||||
#include "platform_if.h"
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static int
|
||||
socfpga_devmap_init(platform_t plat)
|
||||
{
|
||||
|
||||
/* UART */
|
||||
devmap_add_entry(0xffc00000, 0x100000);
|
||||
|
||||
/*
|
||||
* USB OTG
|
||||
*
|
||||
* We use static device map for USB due to some bug in the Altera
|
||||
* which throws Translation Fault (P) exception on high load.
|
||||
* It might be caused due to some power save options being turned
|
||||
* on or something else.
|
||||
*/
|
||||
devmap_add_entry(0xffb00000, 0x100000);
|
||||
|
||||
/* dwmmc */
|
||||
devmap_add_entry(0xff700000, 0x100000);
|
||||
|
||||
/* scu */
|
||||
devmap_add_entry(0xfff00000, 0x100000);
|
||||
|
||||
/* FPGA memory window, 256MB */
|
||||
devmap_add_entry(0xd0000000, 0x10000000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static int
|
||||
socfpga_a10_devmap_init(platform_t plat)
|
||||
{
|
||||
|
||||
/* UART */
|
||||
devmap_add_entry(0xffc00000, 0x100000);
|
||||
|
||||
/* USB OTG */
|
||||
devmap_add_entry(0xffb00000, 0x100000);
|
||||
|
||||
/* dwmmc */
|
||||
devmap_add_entry(0xff800000, 0x100000);
|
||||
|
||||
/* scu */
|
||||
devmap_add_entry(0xfff00000, 0x100000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_socfpga_cpu_reset(bus_size_t reg)
|
||||
{
|
||||
uint32_t paddr;
|
||||
bus_addr_t vaddr;
|
||||
phandle_t node;
|
||||
|
||||
if (rstmgr_warmreset(reg) == 0)
|
||||
goto end;
|
||||
|
||||
node = OF_finddevice("/soc/rstmgr");
|
||||
if (node == -1)
|
||||
goto end;
|
||||
|
||||
if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
|
||||
if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) {
|
||||
bus_space_write_4(fdtbus_bs_tag, vaddr,
|
||||
reg, CTRL_SWWARMRSTREQ);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
while (1);
|
||||
}
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static void
|
||||
socfpga_cpu_reset(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_cpu_reset(RSTMGR_CTRL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static void
|
||||
socfpga_a10_cpu_reset(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_cpu_reset(RSTMGR_A10_CTRL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
static platform_method_t socfpga_methods[] = {
|
||||
PLATFORMMETHOD(platform_devmap_init, socfpga_devmap_init),
|
||||
PLATFORMMETHOD(platform_cpu_reset, socfpga_cpu_reset),
|
||||
#ifdef SMP
|
||||
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
|
||||
PLATFORMMETHOD(platform_mp_start_ap, socfpga_mp_start_ap),
|
||||
#endif
|
||||
PLATFORMMETHOD_END,
|
||||
};
|
||||
FDT_PLATFORM_DEF(socfpga, "socfpga", 0, "altr,socfpga-cyclone5", 200);
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
static platform_method_t socfpga_a10_methods[] = {
|
||||
PLATFORMMETHOD(platform_devmap_init, socfpga_a10_devmap_init),
|
||||
PLATFORMMETHOD(platform_cpu_reset, socfpga_a10_cpu_reset),
|
||||
#ifdef SMP
|
||||
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
|
||||
PLATFORMMETHOD(platform_mp_start_ap, socfpga_a10_mp_start_ap),
|
||||
#endif
|
||||
PLATFORMMETHOD_END,
|
||||
};
|
||||
FDT_PLATFORM_DEF(socfpga_a10, "socfpga", 0, "altr,socfpga-arria10", 200);
|
||||
#endif
|
||||
|
|
@ -1,426 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Altera FPGA Manager.
|
||||
* Chapter 4, Cyclone V Device Handbook (CV-5V2 2014.07.22)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_common.h>
|
||||
|
||||
/* FPGA Manager Module Registers */
|
||||
#define FPGAMGR_STAT 0x0 /* Status Register */
|
||||
#define STAT_MSEL_MASK 0x1f
|
||||
#define STAT_MSEL_SHIFT 3
|
||||
#define STAT_MODE_SHIFT 0
|
||||
#define STAT_MODE_MASK 0x7
|
||||
#define FPGAMGR_CTRL 0x4 /* Control Register */
|
||||
#define CTRL_AXICFGEN (1 << 8)
|
||||
#define CTRL_CDRATIO_MASK 0x3
|
||||
#define CTRL_CDRATIO_SHIFT 6
|
||||
#define CTRL_CFGWDTH_MASK 1
|
||||
#define CTRL_CFGWDTH_SHIFT 9
|
||||
#define CTRL_NCONFIGPULL (1 << 2)
|
||||
#define CTRL_NCE (1 << 1)
|
||||
#define CTRL_EN (1 << 0)
|
||||
#define FPGAMGR_DCLKCNT 0x8 /* DCLK Count Register */
|
||||
#define FPGAMGR_DCLKSTAT 0xC /* DCLK Status Register */
|
||||
#define FPGAMGR_GPO 0x10 /* General-Purpose Output Register */
|
||||
#define FPGAMGR_GPI 0x14 /* General-Purpose Input Register */
|
||||
#define FPGAMGR_MISCI 0x18 /* Miscellaneous Input Register */
|
||||
|
||||
/* Configuration Monitor (MON) Registers */
|
||||
#define GPIO_INTEN 0x830 /* Interrupt Enable Register */
|
||||
#define GPIO_INTMASK 0x834 /* Interrupt Mask Register */
|
||||
#define GPIO_INTTYPE_LEVEL 0x838 /* Interrupt Level Register */
|
||||
#define GPIO_INT_POLARITY 0x83C /* Interrupt Polarity Register */
|
||||
#define GPIO_INTSTATUS 0x840 /* Interrupt Status Register */
|
||||
#define GPIO_RAW_INTSTATUS 0x844 /* Raw Interrupt Status Register */
|
||||
#define GPIO_PORTA_EOI 0x84C /* Clear Interrupt Register */
|
||||
#define PORTA_EOI_NS (1 << 0)
|
||||
#define GPIO_EXT_PORTA 0x850 /* External Port A Register */
|
||||
#define EXT_PORTA_CDP (1 << 10) /* Configuration done */
|
||||
#define GPIO_LS_SYNC 0x860 /* Synchronization Level Register */
|
||||
#define GPIO_VER_ID_CODE 0x86C /* GPIO Version Register */
|
||||
#define GPIO_CONFIG_REG2 0x870 /* Configuration Register 2 */
|
||||
#define GPIO_CONFIG_REG1 0x874 /* Configuration Register 1 */
|
||||
|
||||
#define MSEL_PP16_FAST_NOAES_NODC 0x0
|
||||
#define MSEL_PP16_FAST_AES_NODC 0x1
|
||||
#define MSEL_PP16_FAST_AESOPT_DC 0x2
|
||||
#define MSEL_PP16_SLOW_NOAES_NODC 0x4
|
||||
#define MSEL_PP16_SLOW_AES_NODC 0x5
|
||||
#define MSEL_PP16_SLOW_AESOPT_DC 0x6
|
||||
#define MSEL_PP32_FAST_NOAES_NODC 0x8
|
||||
#define MSEL_PP32_FAST_AES_NODC 0x9
|
||||
#define MSEL_PP32_FAST_AESOPT_DC 0xa
|
||||
#define MSEL_PP32_SLOW_NOAES_NODC 0xc
|
||||
#define MSEL_PP32_SLOW_AES_NODC 0xd
|
||||
#define MSEL_PP32_SLOW_AESOPT_DC 0xe
|
||||
|
||||
#define CFGWDTH_16 0
|
||||
#define CFGWDTH_32 1
|
||||
|
||||
#define CDRATIO_1 0
|
||||
#define CDRATIO_2 1
|
||||
#define CDRATIO_4 2
|
||||
#define CDRATIO_8 3
|
||||
|
||||
#define FPGAMGR_MODE_POWEROFF 0x0
|
||||
#define FPGAMGR_MODE_RESET 0x1
|
||||
#define FPGAMGR_MODE_CONFIG 0x2
|
||||
#define FPGAMGR_MODE_INIT 0x3
|
||||
#define FPGAMGR_MODE_USER 0x4
|
||||
|
||||
struct cfgmgr_mode {
|
||||
int msel;
|
||||
int cfgwdth;
|
||||
int cdratio;
|
||||
};
|
||||
|
||||
static struct cfgmgr_mode cfgmgr_modes[] = {
|
||||
{ MSEL_PP16_FAST_NOAES_NODC, CFGWDTH_16, CDRATIO_1 },
|
||||
{ MSEL_PP16_FAST_AES_NODC, CFGWDTH_16, CDRATIO_2 },
|
||||
{ MSEL_PP16_FAST_AESOPT_DC, CFGWDTH_16, CDRATIO_4 },
|
||||
{ MSEL_PP16_SLOW_NOAES_NODC, CFGWDTH_16, CDRATIO_1 },
|
||||
{ MSEL_PP16_SLOW_AES_NODC, CFGWDTH_16, CDRATIO_2 },
|
||||
{ MSEL_PP16_SLOW_AESOPT_DC, CFGWDTH_16, CDRATIO_4 },
|
||||
{ MSEL_PP32_FAST_NOAES_NODC, CFGWDTH_32, CDRATIO_1 },
|
||||
{ MSEL_PP32_FAST_AES_NODC, CFGWDTH_32, CDRATIO_4 },
|
||||
{ MSEL_PP32_FAST_AESOPT_DC, CFGWDTH_32, CDRATIO_8 },
|
||||
{ MSEL_PP32_SLOW_NOAES_NODC, CFGWDTH_32, CDRATIO_1 },
|
||||
{ MSEL_PP32_SLOW_AES_NODC, CFGWDTH_32, CDRATIO_4 },
|
||||
{ MSEL_PP32_SLOW_AESOPT_DC, CFGWDTH_32, CDRATIO_8 },
|
||||
{ -1, -1, -1 },
|
||||
};
|
||||
|
||||
struct fpgamgr_softc {
|
||||
struct resource *res[3];
|
||||
bus_space_tag_t bst_data;
|
||||
bus_space_handle_t bsh_data;
|
||||
struct cdev *mgr_cdev;
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
static struct resource_spec fpgamgr_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
fpgamgr_state_get(struct fpgamgr_softc *sc)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = READ4(sc, FPGAMGR_STAT);
|
||||
reg >>= STAT_MODE_SHIFT;
|
||||
reg &= STAT_MODE_MASK;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static int
|
||||
fpgamgr_state_wait(struct fpgamgr_softc *sc, int state)
|
||||
{
|
||||
int tout;
|
||||
|
||||
tout = 1000;
|
||||
while (tout > 0) {
|
||||
if (fpgamgr_state_get(sc) == state)
|
||||
break;
|
||||
tout--;
|
||||
DELAY(10);
|
||||
}
|
||||
if (tout == 0) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_open(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct fpgamgr_softc *sc;
|
||||
struct cfgmgr_mode *mode;
|
||||
int msel;
|
||||
int reg;
|
||||
int i;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
msel = READ4(sc, FPGAMGR_STAT);
|
||||
msel >>= STAT_MSEL_SHIFT;
|
||||
msel &= STAT_MSEL_MASK;
|
||||
|
||||
mode = NULL;
|
||||
for (i = 0; cfgmgr_modes[i].msel != -1; i++) {
|
||||
if (msel == cfgmgr_modes[i].msel) {
|
||||
mode = &cfgmgr_modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mode == NULL) {
|
||||
device_printf(sc->dev, "Can't configure: unknown mode\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg &= ~(CTRL_CDRATIO_MASK << CTRL_CDRATIO_SHIFT);
|
||||
reg |= (mode->cdratio << CTRL_CDRATIO_SHIFT);
|
||||
reg &= ~(CTRL_CFGWDTH_MASK << CTRL_CFGWDTH_SHIFT);
|
||||
reg |= (mode->cfgwdth << CTRL_CFGWDTH_SHIFT);
|
||||
reg &= ~(CTRL_NCE);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
/* Enable configuration */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg |= (CTRL_EN);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
/* Reset FPGA */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg |= (CTRL_NCONFIGPULL);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
/* Wait reset state */
|
||||
if (fpgamgr_state_wait(sc, FPGAMGR_MODE_RESET)) {
|
||||
device_printf(sc->dev, "Can't get RESET state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Release from reset */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg &= ~(CTRL_NCONFIGPULL);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
if (fpgamgr_state_wait(sc, FPGAMGR_MODE_CONFIG)) {
|
||||
device_printf(sc->dev, "Can't get CONFIG state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Clear nSTATUS edge interrupt */
|
||||
WRITE4(sc, GPIO_PORTA_EOI, PORTA_EOI_NS);
|
||||
|
||||
/* Enter configuration state */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg |= (CTRL_AXICFGEN);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_wait_dclk_pulses(struct fpgamgr_softc *sc, int npulses)
|
||||
{
|
||||
int tout;
|
||||
|
||||
/* Clear done bit, if any */
|
||||
if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
|
||||
WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
|
||||
|
||||
/* Request DCLK pulses */
|
||||
WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
|
||||
|
||||
/* Wait finish */
|
||||
tout = 1000;
|
||||
while (tout > 0) {
|
||||
if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
|
||||
WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
|
||||
break;
|
||||
}
|
||||
tout--;
|
||||
DELAY(10);
|
||||
}
|
||||
if (tout == 0) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_close(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct fpgamgr_softc *sc;
|
||||
int reg;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
reg = READ4(sc, GPIO_EXT_PORTA);
|
||||
if ((reg & EXT_PORTA_CDP) == 0) {
|
||||
device_printf(sc->dev, "Err: configuration failed\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Exit configuration state */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg &= ~(CTRL_AXICFGEN);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
/* Wait dclk pulses */
|
||||
if (fpga_wait_dclk_pulses(sc, 4)) {
|
||||
device_printf(sc->dev, "Can't proceed 4 dclk pulses\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (fpgamgr_state_wait(sc, FPGAMGR_MODE_USER)) {
|
||||
device_printf(sc->dev, "Can't get USER mode\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Disable configuration */
|
||||
reg = READ4(sc, FPGAMGR_CTRL);
|
||||
reg &= ~(CTRL_EN);
|
||||
WRITE4(sc, FPGAMGR_CTRL, reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct fpgamgr_softc *sc;
|
||||
int buffer;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
/*
|
||||
* Device supports 4-byte copy only.
|
||||
* TODO: add padding for <4 bytes.
|
||||
*/
|
||||
|
||||
while (uio->uio_resid > 0) {
|
||||
uiomove(&buffer, 4, uio);
|
||||
bus_space_write_4(sc->bst_data, sc->bsh_data,
|
||||
0x0, buffer);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cdevsw fpga_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = fpga_open,
|
||||
.d_close = fpga_close,
|
||||
.d_write = fpga_write,
|
||||
.d_ioctl = fpga_ioctl,
|
||||
.d_name = "FPGA Manager",
|
||||
};
|
||||
|
||||
static int
|
||||
fpgamgr_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,socfpga-fpga-mgr"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "FPGA Manager");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
fpgamgr_attach(device_t dev)
|
||||
{
|
||||
struct fpgamgr_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, fpgamgr_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst_data = rman_get_bustag(sc->res[1]);
|
||||
sc->bsh_data = rman_get_bushandle(sc->res[1]);
|
||||
|
||||
sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
0600, "fpga%d", device_get_unit(sc->dev));
|
||||
|
||||
if (sc->mgr_cdev == NULL) {
|
||||
device_printf(dev, "Failed to create character device.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->mgr_cdev->si_drv1 = sc;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t fpgamgr_methods[] = {
|
||||
DEVMETHOD(device_probe, fpgamgr_probe),
|
||||
DEVMETHOD(device_attach, fpgamgr_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t fpgamgr_driver = {
|
||||
"fpgamgr",
|
||||
fpgamgr_methods,
|
||||
sizeof(struct fpgamgr_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(fpgamgr, simplebus, fpgamgr_driver, 0, 0);
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_platform.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/smp.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/intr.h>
|
||||
#include <machine/platformvar.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_mp.h>
|
||||
#include <arm/altera/socfpga/socfpga_rstmgr.h>
|
||||
|
||||
#define SCU_PHYSBASE 0xFFFEC000
|
||||
#define SCU_PHYSBASE_A10 0xFFFFC000
|
||||
#define SCU_SIZE 0x100
|
||||
|
||||
#define SCU_CONTROL_REG 0x00
|
||||
#define SCU_CONTROL_ENABLE (1 << 0)
|
||||
#define SCU_CONFIG_REG 0x04
|
||||
#define SCU_CONFIG_REG_NCPU_MASK 0x03
|
||||
#define SCU_CPUPOWER_REG 0x08
|
||||
#define SCU_INV_TAGS_REG 0x0c
|
||||
#define SCU_DIAG_CONTROL 0x30
|
||||
#define SCU_DIAG_DISABLE_MIGBIT (1 << 0)
|
||||
#define SCU_FILTER_START_REG 0x40
|
||||
#define SCU_FILTER_END_REG 0x44
|
||||
#define SCU_SECURE_ACCESS_REG 0x50
|
||||
#define SCU_NONSECURE_ACCESS_REG 0x54
|
||||
|
||||
#define RSTMGR_PHYSBASE 0xFFD05000
|
||||
#define RSTMGR_SIZE 0x100
|
||||
|
||||
#define RAM_PHYSBASE 0x0
|
||||
#define RAM_SIZE 0x1000
|
||||
|
||||
#define SOCFPGA_ARRIA10 1
|
||||
#define SOCFPGA_CYCLONE5 2
|
||||
|
||||
extern char *mpentry_addr;
|
||||
static void socfpga_trampoline(void);
|
||||
|
||||
static void
|
||||
socfpga_trampoline(void)
|
||||
{
|
||||
|
||||
__asm __volatile(
|
||||
"ldr pc, 1f\n"
|
||||
".globl mpentry_addr\n"
|
||||
"mpentry_addr:\n"
|
||||
"1: .space 4\n");
|
||||
}
|
||||
|
||||
void
|
||||
socfpga_mp_setmaxid(platform_t plat)
|
||||
{
|
||||
int hwcpu, ncpu;
|
||||
|
||||
/* If we've already set this don't bother to do it again. */
|
||||
if (mp_ncpus != 0)
|
||||
return;
|
||||
|
||||
hwcpu = 2;
|
||||
|
||||
ncpu = hwcpu;
|
||||
TUNABLE_INT_FETCH("hw.ncpu", &ncpu);
|
||||
if (ncpu < 1 || ncpu > hwcpu)
|
||||
ncpu = hwcpu;
|
||||
|
||||
mp_ncpus = ncpu;
|
||||
mp_maxid = ncpu - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
_socfpga_mp_start_ap(uint32_t platid)
|
||||
{
|
||||
bus_space_handle_t scu, rst, ram;
|
||||
int reg;
|
||||
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE_A10,
|
||||
SCU_SIZE, 0, &scu) != 0)
|
||||
panic("Couldn't map the SCU\n");
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE,
|
||||
SCU_SIZE, 0, &scu) != 0)
|
||||
panic("Couldn't map the SCU\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
if (bus_space_map(fdtbus_bs_tag, RSTMGR_PHYSBASE,
|
||||
RSTMGR_SIZE, 0, &rst) != 0)
|
||||
panic("Couldn't map the reset manager (RSTMGR)\n");
|
||||
if (bus_space_map(fdtbus_bs_tag, RAM_PHYSBASE,
|
||||
RAM_SIZE, 0, &ram) != 0)
|
||||
panic("Couldn't map the first physram page\n");
|
||||
|
||||
/* Invalidate SCU cache tags */
|
||||
bus_space_write_4(fdtbus_bs_tag, scu,
|
||||
SCU_INV_TAGS_REG, 0x0000ffff);
|
||||
|
||||
/*
|
||||
* Erratum ARM/MP: 764369 (problems with cache maintenance).
|
||||
* Setting the "disable-migratory bit" in the undocumented SCU
|
||||
* Diagnostic Control Register helps work around the problem.
|
||||
*/
|
||||
reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL);
|
||||
reg |= (SCU_DIAG_DISABLE_MIGBIT);
|
||||
bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL, reg);
|
||||
|
||||
/* Put CPU1 to reset state */
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_A10_MPUMODRST, MPUMODRST_CPU1);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_MPUMODRST, MPUMODRST_CPU1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
/* Enable the SCU, then clean the cache on this core */
|
||||
reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
|
||||
reg |= (SCU_CONTROL_ENABLE);
|
||||
bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, reg);
|
||||
|
||||
/* Set up trampoline code */
|
||||
mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry);
|
||||
bus_space_write_region_4(fdtbus_bs_tag, ram, 0,
|
||||
(uint32_t *)&socfpga_trampoline, 8);
|
||||
|
||||
dcache_wbinv_poc_all();
|
||||
|
||||
/* Put CPU1 out from reset */
|
||||
switch (platid) {
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
case SOCFPGA_ARRIA10:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_A10_MPUMODRST, 0);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
case SOCFPGA_CYCLONE5:
|
||||
bus_space_write_4(fdtbus_bs_tag, rst,
|
||||
RSTMGR_MPUMODRST, 0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown platform id %d\n", platid);
|
||||
}
|
||||
|
||||
dsb();
|
||||
sev();
|
||||
|
||||
bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
|
||||
bus_space_unmap(fdtbus_bs_tag, rst, RSTMGR_SIZE);
|
||||
bus_space_unmap(fdtbus_bs_tag, ram, RAM_SIZE);
|
||||
}
|
||||
|
||||
#if defined(SOC_ALTERA_ARRIA10)
|
||||
void
|
||||
socfpga_a10_mp_start_ap(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_mp_start_ap(SOCFPGA_ARRIA10);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOC_ALTERA_CYCLONE5)
|
||||
void
|
||||
socfpga_mp_start_ap(platform_t plat)
|
||||
{
|
||||
|
||||
_socfpga_mp_start_ap(SOCFPGA_CYCLONE5);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Andrew Turner <andrew@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SOCFPGA_MP_H_
|
||||
#define _SOCFPGA_MP_H_
|
||||
|
||||
void socfpga_mp_setmaxid(platform_t);
|
||||
void socfpga_mp_start_ap(platform_t);
|
||||
void socfpga_a10_mp_start_ap(platform_t);
|
||||
|
||||
#endif /* _SOCFPGA_MP_H_ */
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SOCFPGA Reset Manager.
|
||||
* Chapter 3, Cyclone V Device Handbook (CV-5V2 2014.07.22)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <arm/altera/socfpga/socfpga_common.h>
|
||||
#include <arm/altera/socfpga/socfpga_rstmgr.h>
|
||||
#include <arm/altera/socfpga/socfpga_l3regs.h>
|
||||
|
||||
struct rstmgr_softc {
|
||||
struct resource *res[1];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
struct rstmgr_softc *rstmgr_sc;
|
||||
|
||||
static struct resource_spec rstmgr_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
enum {
|
||||
RSTMGR_SYSCTL_FPGA2HPS,
|
||||
RSTMGR_SYSCTL_LWHPS2FPGA,
|
||||
RSTMGR_SYSCTL_HPS2FPGA
|
||||
};
|
||||
|
||||
static int
|
||||
l3remap(struct rstmgr_softc *sc, int remap, int enable)
|
||||
{
|
||||
uint32_t paddr;
|
||||
bus_addr_t vaddr;
|
||||
phandle_t node;
|
||||
int reg;
|
||||
|
||||
/*
|
||||
* Control whether bridge is visible to L3 masters or not.
|
||||
* Register is write-only.
|
||||
*/
|
||||
|
||||
reg = REMAP_MPUZERO;
|
||||
if (enable)
|
||||
reg |= (remap);
|
||||
else
|
||||
reg &= ~(remap);
|
||||
|
||||
node = OF_finddevice("l3regs");
|
||||
if (node == -1) {
|
||||
device_printf(sc->dev, "Can't find l3regs node\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
|
||||
if (bus_space_map(fdtbus_bs_tag, paddr, 0x4, 0, &vaddr) == 0) {
|
||||
bus_space_write_4(fdtbus_bs_tag, vaddr,
|
||||
L3REGS_REMAP, reg);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
rstmgr_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct rstmgr_softc *sc;
|
||||
int enable;
|
||||
int remap;
|
||||
int err;
|
||||
int reg;
|
||||
int bit;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
switch (arg2) {
|
||||
case RSTMGR_SYSCTL_FPGA2HPS:
|
||||
bit = BRGMODRST_FPGA2HPS;
|
||||
remap = 0;
|
||||
break;
|
||||
case RSTMGR_SYSCTL_LWHPS2FPGA:
|
||||
bit = BRGMODRST_LWHPS2FPGA;
|
||||
remap = REMAP_LWHPS2FPGA;
|
||||
break;
|
||||
case RSTMGR_SYSCTL_HPS2FPGA:
|
||||
bit = BRGMODRST_HPS2FPGA;
|
||||
remap = REMAP_HPS2FPGA;
|
||||
break;
|
||||
default:
|
||||
return (1);
|
||||
}
|
||||
|
||||
reg = READ4(sc, RSTMGR_BRGMODRST);
|
||||
enable = reg & bit ? 0 : 1;
|
||||
|
||||
err = sysctl_handle_int(oidp, &enable, 0, req);
|
||||
if (err || !req->newptr)
|
||||
return (err);
|
||||
|
||||
if (enable == 1)
|
||||
reg &= ~(bit);
|
||||
else if (enable == 0)
|
||||
reg |= (bit);
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
WRITE4(sc, RSTMGR_BRGMODRST, reg);
|
||||
l3remap(sc, remap, enable);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rstmgr_warmreset(uint32_t reg)
|
||||
{
|
||||
struct rstmgr_softc *sc;
|
||||
|
||||
sc = rstmgr_sc;
|
||||
if (sc == NULL)
|
||||
return (1);
|
||||
|
||||
/* Request warm reset */
|
||||
WRITE4(sc, reg, CTRL_SWWARMRSTREQ);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rstmgr_add_sysctl(struct rstmgr_softc *sc)
|
||||
{
|
||||
struct sysctl_oid_list *children;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
|
||||
ctx = device_get_sysctl_ctx(sc->dev);
|
||||
children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fpga2hps",
|
||||
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
||||
sc, RSTMGR_SYSCTL_FPGA2HPS,
|
||||
rstmgr_sysctl, "I", "Enable fpga2hps bridge");
|
||||
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "lwhps2fpga",
|
||||
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
||||
sc, RSTMGR_SYSCTL_LWHPS2FPGA,
|
||||
rstmgr_sysctl, "I", "Enable lwhps2fpga bridge");
|
||||
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "hps2fpga",
|
||||
CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
||||
sc, RSTMGR_SYSCTL_HPS2FPGA,
|
||||
rstmgr_sysctl, "I", "Enable hps2fpga bridge");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rstmgr_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,rst-mgr"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Reset Manager");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
rstmgr_attach(device_t dev)
|
||||
{
|
||||
struct rstmgr_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, rstmgr_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
rstmgr_sc = sc;
|
||||
rstmgr_add_sysctl(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t rstmgr_methods[] = {
|
||||
DEVMETHOD(device_probe, rstmgr_probe),
|
||||
DEVMETHOD(device_attach, rstmgr_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t rstmgr_driver = {
|
||||
"rstmgr",
|
||||
rstmgr_methods,
|
||||
sizeof(struct rstmgr_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(rstmgr, simplebus, rstmgr_driver, 0, 0);
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define RSTMGR_STAT 0x0 /* Status */
|
||||
#define RSTMGR_CTRL 0x4 /* Control */
|
||||
#define CTRL_SWWARMRSTREQ (1 << 1) /* Trigger warm reset */
|
||||
#define RSTMGR_COUNTS 0x8 /* Reset Cycles Count */
|
||||
#define RSTMGR_MPUMODRST 0x10 /* MPU Module Reset */
|
||||
#define MPUMODRST_CPU1 (1 << 1)
|
||||
#define RSTMGR_PERMODRST 0x14 /* Peripheral Module Reset */
|
||||
#define RSTMGR_PER2MODRST 0x18 /* Peripheral 2 Module Reset */
|
||||
#define RSTMGR_BRGMODRST 0x1C /* Bridge Module Reset */
|
||||
#define BRGMODRST_FPGA2HPS (1 << 2)
|
||||
#define BRGMODRST_LWHPS2FPGA (1 << 1)
|
||||
#define BRGMODRST_HPS2FPGA (1 << 0)
|
||||
#define RSTMGR_MISCMODRST 0x20 /* Miscellaneous Module Reset */
|
||||
|
||||
#define RSTMGR_A10_CTRL 0xC /* Control */
|
||||
#define RSTMGR_A10_MPUMODRST 0x20 /* MPU Module Reset */
|
||||
|
||||
int rstmgr_warmreset(uint32_t reg);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
cpu CPU_CORTEXA
|
||||
machine arm armv7
|
||||
makeoptions CONF_CFLAGS="-march=armv7a"
|
||||
|
||||
files "../altera/socfpga/files.socfpga"
|
||||
|
|
@ -856,18 +856,6 @@ contrib/alpine-hal/eth/al_hal_eth_main.c optional al_eth \
|
|||
dev/alc/if_alc.c optional alc pci
|
||||
dev/ale/if_ale.c optional ale pci
|
||||
dev/alpm/alpm.c optional alpm pci
|
||||
dev/altera/avgen/altera_avgen.c optional altera_avgen
|
||||
dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt
|
||||
dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen
|
||||
dev/altera/msgdma/msgdma.c optional altera_msgdma xdma
|
||||
dev/altera/sdcard/altera_sdcard.c optional altera_sdcard
|
||||
dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard
|
||||
dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard
|
||||
dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt
|
||||
dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard
|
||||
dev/altera/softdma/softdma.c optional altera_softdma xdma fdt
|
||||
dev/altera/pio/pio.c optional altera_pio
|
||||
dev/altera/pio/pio_if.m optional altera_pio
|
||||
dev/amdpm/amdpm.c optional amdpm pci | nfpm pci
|
||||
dev/amdsmb/amdsmb.c optional amdsmb pci
|
||||
#
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ TSLOGSIZE opt_global.h
|
|||
|
||||
# Miscellaneous options.
|
||||
ALQ
|
||||
ALTERA_SDCARD_FAST_SIM opt_altera_sdcard.h
|
||||
ATSE_CFI_HACK opt_cfi.h
|
||||
AUDIT opt_global.h
|
||||
BOOTHOWTO opt_global.h
|
||||
|
|
@ -838,12 +837,6 @@ AH_INTERRUPT_DEBUGGING opt_ah.h
|
|||
# XXX do not use this for AR9130
|
||||
AH_AR5416_INTERRUPT_MITIGATION opt_ah.h
|
||||
|
||||
# options for the Altera mSGDMA driver (altera_msgdma)
|
||||
ALTERA_MSGDMA_DESC_STD opt_altera_msgdma.h
|
||||
ALTERA_MSGDMA_DESC_EXT opt_altera_msgdma.h
|
||||
ALTERA_MSGDMA_DESC_PF_STD opt_altera_msgdma.h
|
||||
ALTERA_MSGDMA_DESC_PF_EXT opt_altera_msgdma.h
|
||||
|
||||
# options for the Broadcom BCM43xx driver (bwi)
|
||||
BWI_DEBUG opt_bwi.h
|
||||
BWI_DEBUG_VERBOSE opt_bwi.h
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,144 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2013 Bjoern A. Zeeb
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
|
||||
* ("MRC2"), as part of the DARPA MRC research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/altera/atse/if_atsereg.h>
|
||||
|
||||
/* "device miibus" required. See GENERIC if you get errors here. */
|
||||
#include "miibus_if.h"
|
||||
|
||||
static int
|
||||
atse_probe_fdt(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altera,atse")) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
atse_attach_fdt(device_t dev)
|
||||
{
|
||||
struct atse_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->atse_dev = dev;
|
||||
sc->atse_unit = device_get_unit(dev);
|
||||
|
||||
/*
|
||||
* FDT has the list of our resources. Given we are using multiple
|
||||
* memory regions and possibly multiple interrupts, we need to attach
|
||||
* them in the order specified in .dts:
|
||||
* MAC, RX and RXC FIFO, TX and TXC FIFO; RX INTR, TX INTR.
|
||||
*/
|
||||
|
||||
/* MAC: Avalon-MM, atse management register region. */
|
||||
sc->atse_mem_rid = 0;
|
||||
sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->atse_mem_rid, RF_ACTIVE);
|
||||
if (sc->atse_mem_res == NULL) {
|
||||
device_printf(dev, "failed to map memory for ctrl region\n");
|
||||
/* Cleanup. */
|
||||
atse_detach_resources(dev);
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(sc->atse_dev, "MAC ctrl region at mem %p-%p\n",
|
||||
(void *)rman_get_start(sc->atse_mem_res),
|
||||
(void *)(rman_get_start(sc->atse_mem_res) +
|
||||
rman_get_size(sc->atse_mem_res)));
|
||||
|
||||
error = atse_attach(dev);
|
||||
if (error) {
|
||||
/* Cleanup. */
|
||||
atse_detach_resources(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t atse_methods_fdt[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, atse_probe_fdt),
|
||||
DEVMETHOD(device_attach, atse_attach_fdt),
|
||||
DEVMETHOD(device_detach, atse_detach_dev),
|
||||
|
||||
/* MII interface */
|
||||
DEVMETHOD(miibus_readreg, atse_miibus_readreg),
|
||||
DEVMETHOD(miibus_writereg, atse_miibus_writereg),
|
||||
DEVMETHOD(miibus_statchg, atse_miibus_statchg),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t atse_driver_fdt = {
|
||||
"atse",
|
||||
atse_methods_fdt,
|
||||
sizeof(struct atse_softc)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(atse, simplebus, atse_driver_fdt, 0, 0);
|
||||
DRIVER_MODULE(miibus, atse, miibus_driver, 0, 0);
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012,2013 Bjoern A. Zeeb
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
|
||||
* ("MRC2"), as part of the DARPA MRC research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_device_polling.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
|
||||
#include <dev/altera/atse/if_atsereg.h>
|
||||
|
||||
/* "device miibus" required. See GENERIC if you get errors here. */
|
||||
#include "miibus_if.h"
|
||||
|
||||
MODULE_DEPEND(atse, ether, 1, 1, 1);
|
||||
MODULE_DEPEND(atse, miibus, 1, 1, 1);
|
||||
|
||||
/*
|
||||
* Device routines for interacting with nexus (probe, attach, detach) & helpers.
|
||||
* XXX We should add suspend/resume later.
|
||||
*/
|
||||
static int __unused
|
||||
atse_resource_int(device_t dev, const char *resname, int *v)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
resname, v);
|
||||
if (error != 0) {
|
||||
/* If it does not exist, we fail, so not ingoring ENOENT. */
|
||||
device_printf(dev, "could not fetch '%s' hint\n", resname);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int __unused
|
||||
atse_resource_long(device_t dev, const char *resname, long *v)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = resource_long_value(device_get_name(dev), device_get_unit(dev),
|
||||
resname, v);
|
||||
if (error != 0) {
|
||||
/* If it does not exist, we fail, so not ingoring ENOENT. */
|
||||
device_printf(dev, "could not fetch '%s' hint\n", resname);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
atse_probe_nexus(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
|
||||
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
atse_attach_nexus(device_t dev)
|
||||
{
|
||||
struct atse_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->atse_dev = dev;
|
||||
sc->atse_unit = device_get_unit(dev);
|
||||
|
||||
/* Avalon-MM, atse management register region. */
|
||||
sc->atse_mem_rid = 0;
|
||||
sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->atse_mem_rid, RF_ACTIVE);
|
||||
if (sc->atse_mem_res == NULL) {
|
||||
device_printf(dev, "failed to map memory for ctrl region\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
error = atse_attach(dev);
|
||||
if (error) {
|
||||
/* Cleanup. */
|
||||
atse_detach_resources(dev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t atse_methods_nexus[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, atse_probe_nexus),
|
||||
DEVMETHOD(device_attach, atse_attach_nexus),
|
||||
DEVMETHOD(device_detach, atse_detach_dev),
|
||||
|
||||
/* MII interface */
|
||||
DEVMETHOD(miibus_readreg, atse_miibus_readreg),
|
||||
DEVMETHOD(miibus_writereg, atse_miibus_writereg),
|
||||
DEVMETHOD(miibus_statchg, atse_miibus_statchg),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t atse_driver_nexus = {
|
||||
"atse",
|
||||
atse_methods_nexus,
|
||||
sizeof(struct atse_softc)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(atse, nexus, atse_driver_nexus, 0, 0);
|
||||
DRIVER_MODULE(miibus, atse, miibus_driver, 0, 0);
|
||||
|
|
@ -1,464 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Bjoern A. Zeeb
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
|
||||
* ("MRC2"), as part of the DARPA MRC research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_IF_ATSEREG_H
|
||||
#define _DEV_IF_ATSEREG_H
|
||||
|
||||
#include <dev/xdma/xdma.h>
|
||||
|
||||
#define ATSE_VENDOR 0x6af7
|
||||
#define ATSE_DEVICE 0x00bd
|
||||
|
||||
/* See hints file/fdt for ctrl port and Avalon FIFO addresses. */
|
||||
|
||||
/* Section 3. Parameter Settings. */
|
||||
/*
|
||||
* This is a lot of options that affect the way things are synthesized.
|
||||
* We cannot really make them all hints and most of them might be stale.
|
||||
*/
|
||||
|
||||
/* 3-1 Core Configuration */
|
||||
#if 0
|
||||
static const char *atse_core_core_variation[] = {
|
||||
[0] = "10/100/1000 Mbps Ethernet MAC only",
|
||||
[1] = "10/100/1000 Mbps Ethernet MAC with 1000BASE-X/SGMII PCS",
|
||||
[2] = "1000BASE-X/SGMII PCS only",
|
||||
[3] = "1000 Mbps Small MAC",
|
||||
[4] = "10/100 Mbps Small MAC",
|
||||
NULL
|
||||
};
|
||||
static const char *atse_core_interface[] = {
|
||||
[0] = "MII", /* Core variation 4. */
|
||||
[1] = "GMII", /* Core variation 3. */
|
||||
[2] = "RGMII", /* Core variation 0,1,3. */
|
||||
[3] = "MII/GMII", /* Core variation 0,1. */
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
#define CORE_CORE_VARIATION 1 /* atse_core_core_variation[] */
|
||||
#define CORE_INTERFACE 3 /* atse_core_interface[] */
|
||||
#define CORE_USE_INTERNAL_FIFO 1
|
||||
#define CORE_NUMBER_OF_PORTS 1 /* Internal FIFO count. */
|
||||
#define CORE_USE_TRANSCEIVER_BLOCK 1 /* SGMII PCS transceiver:
|
||||
* LVDS I/O. */
|
||||
|
||||
/* 3-2 MAC Options. */
|
||||
/* Ethernet MAC Options. */
|
||||
#define MAC_ENABLE_10_100_HDX_SUPPORT 0
|
||||
#define MAC_ENABLE_RG_G_MII_LOOPBACK 0
|
||||
#define MAC_ENABLE_SUPL_MAC_UCAST_ADDR 0 /* Supplementary MAC unicast. */
|
||||
#define MAC_INCLUDE_STATISTICS_COUNTERS 0
|
||||
#define MAC_STATISTICS_COUNTERS_64BIT 0
|
||||
#define MAC_INCLUDE_MC_HASHTABLE 0 /* Multicast. */
|
||||
#define MAC_ALIGN_PKTHDR_32BIT 1
|
||||
#define MAC_ENABLE_FDX_FLOW_CTRL 0
|
||||
#define MAC_ENABLE_VLAN_DETECTION 0 /* VLAN and stacked VLANs. */
|
||||
#define MAC_ENABLE_MAGIC_PKT_DETECTION 0
|
||||
/* MDIO Module. */
|
||||
#define MAC_MDIO_INCLUDE_MDIO_MODULE 1
|
||||
#define MAC_MDIO_HOST_CLOCK_DIVISOR 40 /* Not just On/Off. */
|
||||
|
||||
/* 3-4 FIFO Options. */
|
||||
/* Width and Memory Type. */
|
||||
#if 0
|
||||
static char *fifo_memory_block[] = {
|
||||
[0] = "M4K",
|
||||
[1] = "M9K",
|
||||
[2] = "M144K",
|
||||
[3] = "MRAM",
|
||||
[4] = "AUTO",
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
#define FIFO_MEMORY_BLOCK 4
|
||||
#define FIFO_WITDH 32 /* Other: 8 bits. */
|
||||
/* Depth. */
|
||||
#define FIFO_DEPTH_TX 2048 /* 64 .. 64k, 2048x32bits. */
|
||||
#define FIFO_DEPTH_RX 2048 /* 64 .. 64k, 2048x32bits. */
|
||||
|
||||
#define ATSE_TX_LIST_CNT 5 /* Certainly not bufferbloat. */
|
||||
|
||||
/* 3-4 PCS/Transceiver Options */
|
||||
/* PCS Options. */
|
||||
#define PCS_TXRX_PHY_ID 0x00000000 /* 32 bits */
|
||||
#define PCS_TXRX_ENABLE_SGMII_BRIDGE 0
|
||||
/* Transceiver Options. */
|
||||
#define PCS_TXRX_EXP_POWER_DOWN_SIGNAL 0 /* Export power down signal. */
|
||||
#define PCS_TXRX_ENABLE_DYNAMIC_RECONF 0 /* Dynamic trans. reconfig. */
|
||||
#define PCS_TXRX_STARTING_CHANNEL 0 /* 0..284. */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* XXX more values based on the bitmaps provided. Cleanup. */
|
||||
/* See regs above. */
|
||||
#define AVALON_FIFO_TX_BLOCK_DIAGRAM 0
|
||||
#define AVALON_FIFO_TX_BLOCK_DIAGRAM_SHOW_SIGANLS 0
|
||||
#define AVALON_FIFO_TX_PARAM_SINGLE_RESET_MODE 0
|
||||
#define AVALON_FIFO_TX_BASIC_OPTS_DEPTH 16
|
||||
#define AVALON_FIFO_TX_BASIC_OPTS_ALLOW_BACKPRESSURE 1
|
||||
#define AVALON_FIFO_TX_BASIC_OPTS_CLOCK_SETTING "Single Clock Mode"
|
||||
#define AVALON_FIFO_TX_BASIC_OPTS_FIFO_IMPL "Construct FIFO from embedded memory blocks"
|
||||
#define AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT 1
|
||||
#define AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT 0
|
||||
#define AVALON_FIFO_TX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT 1
|
||||
#define AVALON_FIFO_TX_INPUT_TYPE "AVALONMM_WRITE"
|
||||
#define AVALON_FIFO_TX_OUTPUT_TYPE "AVALONST_SOURCE"
|
||||
#define AVALON_FIFO_TX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH ""
|
||||
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL 8
|
||||
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT 4
|
||||
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH 1
|
||||
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH 0
|
||||
#define AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA 1
|
||||
|
||||
#define AVALON_FIFO_RX_BLOCK_DIAGRAM 0
|
||||
#define AVALON_FIFO_RX_BLOCK_DIAGRAM_SHOW_SIGNALS 0
|
||||
#define AVALON_FIFO_RX_PARAM_SINGLE_RESET_MODE 0
|
||||
#define AVALON_FIFO_RX_BASIC_OPTS_DEPTH 16
|
||||
#define AVALON_FIFO_RX_BASIC_OPTS_ALLOW_BACKPRESSURE 1
|
||||
#define AVALON_FIFO_RX_BASIC_OPTS_CLOCK_SETTING "Single Clock Mode"
|
||||
#define AVALON_FIFO_RX_BASIC_OPTS_FIFO_IMPL "Construct FIFO from embedded memory blocks"
|
||||
#define AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT 1
|
||||
#define AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT 0
|
||||
#define AVALON_FIFO_RX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT 1
|
||||
#define AVALON_FIFO_RX_INPUT_TYPE "AVALONST_SINK"
|
||||
#define AVALON_FIFO_RX_OUTPUT_TYPE "AVALONMM_READ"
|
||||
#define AVALON_FIFO_RX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH ""
|
||||
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL 8
|
||||
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT 4
|
||||
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH 6
|
||||
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH 0
|
||||
#define AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA 1
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* 5. Configuration Register Space. */
|
||||
|
||||
/* 5-1, MAC Configuration Register Space; Dword offsets. */
|
||||
/* 0x00 - 0x17, Base Configuration. */
|
||||
#define BASE_CONFIG_REV 0x00 /* ro, IP Core ver. */
|
||||
#define BASE_CFG_REV_VER_MASK 0x0000FFFF
|
||||
#define BASE_CFG_REV_CUST_VERSION__MASK 0xFFFF0000
|
||||
|
||||
#define BASE_CFG_SCRATCH 0x01 /* rw, 0 */
|
||||
|
||||
#define BASE_CFG_COMMAND_CONFIG 0x02 /* rw, 0 */
|
||||
#define BASE_CFG_COMMAND_CONFIG_TX_ENA (1<<0) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_RX_ENA (1<<1) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_XON_GEN (1<<2) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_ETH_SPEED (1<<3) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_PROMIS_EN (1<<4) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_PAD_EN (1<<5) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_CRC_FWD (1<<6) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_PAUSE_FWD (1<<7) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_PAUSE_IGNORE (1<<8) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_TX_ADDR_INS (1<<9) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_HD_ENA (1<<10) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_EXCESS_COL (1<<11) /* ro */
|
||||
#define BASE_CFG_COMMAND_CONFIG_LATE_COL (1<<12) /* ro */
|
||||
#define BASE_CFG_COMMAND_CONFIG_SW_RESET (1<<13) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_MHASH_SEL (1<<14) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_LOOP_ENA (1<<15) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_TX_ADDR_SEL (1<<16|1<<17|1<<18) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_MAGIC_ENA (1<<19) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_SLEEP (1<<20) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_WAKEUP (1<<21) /* ro */
|
||||
#define BASE_CFG_COMMAND_CONFIG_XOFF_GEN (1<<22) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_CNTL_FRM_ENA (1<<23) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_NO_LGTH_CHECK (1<<24) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_ENA_10 (1<<25) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC (1<<26) /* rw */
|
||||
#define BASE_CFG_COMMAND_CONFIG_DISABLE_READ_TIMEOUT (1<<27) /* rw */
|
||||
/* 28-30 Reserved. */ /* - */
|
||||
#define BASE_CFG_COMMAND_CONFIG_CNT_RESET (1<<31) /* rw */
|
||||
|
||||
#define BASE_CFG_MAC_0 0x03 /* rw, 0 */
|
||||
#define BASE_CFG_MAC_1 0x04 /* rw, 0 */
|
||||
#define BASE_CFG_FRM_LENGTH 0x05 /* rw/ro, 1518 */
|
||||
#define BASE_CFG_PAUSE_QUANT 0x06 /* rw, 0 */
|
||||
#define BASE_CFG_RX_SECTION_EMPTY 0x07 /* rw/ro, 0 */
|
||||
#define BASE_CFG_RX_SECTION_FULL 0x08 /* rw/ro, 0 */
|
||||
#define BASE_CFG_TX_SECTION_EMPTY 0x09 /* rw/ro, 0 */
|
||||
#define BASE_CFG_TX_SECTION_FULL 0x0A /* rw/ro, 0 */
|
||||
#define BASE_CFG_RX_ALMOST_EMPTY 0x0B /* rw/ro, 0 */
|
||||
#define BASE_CFG_RX_ALMOST_FULL 0x0C /* rw/ro, 0 */
|
||||
#define BASE_CFG_TX_ALMOST_EMPTY 0x0D /* rw/ro, 0 */
|
||||
#define BASE_CFG_TX_ALMOST_FULL 0x0E /* rw/ro, 0 */
|
||||
#define BASE_CFG_MDIO_ADDR0 0x0F /* rw, 0 */
|
||||
#define BASE_CFG_MDIO_ADDR1 0x10 /* rw, 1 */
|
||||
#define BASE_CFG_HOLDOFF_QUANT 0x11 /* rw, 0xFFFF */
|
||||
/* 0x12-0x16 Reserved. */ /* -, 0 */
|
||||
#define BASE_CFG_TX_IPG_LENGTH 0x17 /* rw, 0 */
|
||||
|
||||
/* 0x18 - 0x38, Statistics Counters. */
|
||||
#define STATS_A_MAC_ID_0 0x18 /* ro */
|
||||
#define STATS_A_MAC_ID_1 0x19 /* ro */
|
||||
#define STATS_A_FRAMES_TX_OK 0x1A /* ro */
|
||||
#define STATS_A_FRAMES_RX_OK 0x1B /* ro */
|
||||
#define STATS_A_FCS_ERRORS 0x1C /* ro */
|
||||
#define STATS_A_ALIGNMENT_ERRORS 0x1D /* ro */
|
||||
#define STATS_A_OCTETS_TX_OK 0x1E /* ro */
|
||||
#define STATS_A_OCTETS_RX_OK 0x1F /* ro */
|
||||
#define STATS_A_TX_PAUSE_MAX_CTRL_FRAME 0x20 /* ro */
|
||||
#define STATS_A_RX_PAUSE_MAX_CTRL_FRAME 0x21 /* ro */
|
||||
#define STATS_IF_IN_ERRORS 0x22 /* ro */
|
||||
#define STATS_IF_OUT_ERRORS 0x23 /* ro */
|
||||
#define STATS_IF_IN_UCAST_PKTS 0x24 /* ro */
|
||||
#define STATS_IF_IN_MULTICAST_PKTS 0x25 /* ro */
|
||||
#define STATS_IF_IN_BROADCAST_PKTS 0x26 /* ro */
|
||||
#define STATS_IF_OUT_DISCARDS 0x27 /* ro */
|
||||
#define STATS_IF_OUT_UCAST_PKTS 0x28 /* ro */
|
||||
#define STATS_IF_OUT_MULTICAST_PKTS 0x29 /* ro */
|
||||
#define STATS_IF_OUT_BROADCAST_PKTS 0x2A /* ro */
|
||||
#define STATS_ETHER_STATS_DROP_EVENT 0x2B /* ro */
|
||||
#define STATS_ETHER_STATS_OCTETS 0x2C /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS 0x2D /* ro */
|
||||
#define STATS_ETHER_STATS_USIZE_PKTS 0x2E /* ro */
|
||||
#define STATS_ETHER_STATS_OSIZE_PKTS 0x2F /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_64_OCTETS 0x30 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_65_TO_127_OCTETS 0x31 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_128_TO_255_OCTETS 0x32 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_256_TO_511_OCTETS 0x33 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_512_TO_1023_OCTETS 0x34 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_1024_TO_1518_OCTETS 0x35 /* ro */
|
||||
#define STATS_ETHER_STATS_PKTS_1519_TO_X_OCTETS 0x36 /* ro */
|
||||
#define STATS_ETHER_STATS_JABBERS 0x37 /* ro */
|
||||
#define STATS_ETHER_STATS_FRAGMENTS 0x38 /* ro */
|
||||
/* 0x39, Reserved. */ /* - */
|
||||
|
||||
/* 0x3A, Transmit Command. */
|
||||
#define TX_CMD_STAT 0x3A /* rw */
|
||||
#define TX_CMD_STAT_OMIT_CRC (1<<17)
|
||||
#define TX_CMD_STAT_TX_SHIFT16 (1<<18)
|
||||
|
||||
/* 0x3B, Receive Command. */
|
||||
#define RX_CMD_STAT 0x3B /* rw */
|
||||
#define RX_CMD_STAT_RX_SHIFT16 (1<<25)
|
||||
|
||||
/* 0x3C - 0x3E, Extended Statistics Counters. */
|
||||
#define ESTATS_MSB_A_OCTETS_TX_OK 0x3C /* ro */
|
||||
#define ESTATS_MSB_A_OCTETS_RX_OK 0x3D /* ro */
|
||||
#define ESTATS_MSB_ETHER_STATS_OCTETS 0x3E /* ro */
|
||||
|
||||
/* 0x3F, Reserved. */
|
||||
|
||||
/* 0x40 - 0x7F, Multicast Hash Table. */
|
||||
#define MHASH_START 0x40
|
||||
#define MHASH_LEN 0x3F
|
||||
|
||||
/* 0x80 - 0x9F, MDIO Space 0 or PCS Function Configuration. */
|
||||
#define MDIO_0_START 0x80
|
||||
|
||||
/* The following are offsets to the first PCS register at 0x80. */
|
||||
/* See sys/dev/mii/mii.h. */
|
||||
#define PCS_CONTROL 0x00 /* rw */
|
||||
/* Bits 0:4, Reserved. */ /* - */
|
||||
#define PCS_CONTROL_UNIDIRECTIONAL_ENABLE (1<<5) /* rw */
|
||||
#define PCS_CONTROL_SPEED_SELECTION (1<<6|1<<13) /* ro */
|
||||
#define PCS_CONTROL_COLLISION_TEST (1<<7) /* ro */
|
||||
#define PCS_CONTROL_DUPLEX_MODE (1<<8) /* ro */
|
||||
#define PCS_CONTROL_RESTART_AUTO_NEGOTIATION (1<<9) /* rw */
|
||||
#define PCS_CONTROL_ISOLATE (1<<10) /* rw */
|
||||
#define PCS_CONTROL_POWERDOWN (1<<11) /* rw */
|
||||
#define PCS_CONTROL_AUTO_NEGOTIATION_ENABLE (1<<12) /* rw */
|
||||
/* See bit 6 above. */ /* ro */
|
||||
#define PCS_CONTROL_LOOPBACK (1<<14) /* rw */
|
||||
#define PCS_CONTROL_RESET (1<<15) /* rw */
|
||||
|
||||
#define PCS_STATUS 0x01 /* ro */
|
||||
#define PCS_STATUS_EXTENDED_CAPABILITY (1<<0) /* ro */
|
||||
#define PCS_STATUS_JABBER_DETECT (1<<1) /* -, 0 */
|
||||
#define PCS_STATUS_LINK_STATUS (1<<2) /* ro */
|
||||
#define PCS_STATUS_AUTO_NEGOTIATION_ABILITY (1<<3) /* ro */
|
||||
#define PCS_STATUS_REMOTE_FAULT (1<<4) /* -, 0 */
|
||||
#define PCS_STATUS_AUTO_NEGOTIATION_COMPLETE (1<<5) /* ro */
|
||||
#define PCS_STATUS_MF_PREAMBLE_SUPPRESSION (1<<6) /* -, 0 */
|
||||
#define PCS_STATUS_UNIDIRECTIONAL_ABILITY (1<<7) /* ro */
|
||||
#define PCS_STATUS_EXTENDED_STATUS (1<<8) /* -, 0 */
|
||||
#define PCS_STATUS_100BASET2_HALF_DUPLEX (1<<9) /* ro */
|
||||
#define PCS_STATUS_100BASET2_FULL_DUPLEX (1<<10) /* ro */
|
||||
#define PCS_STATUS_10MBPS_HALF_DUPLEX (1<<11) /* ro */
|
||||
#define PCS_STATUS_10MBPS_FULL_DUPLEX (1<<12) /* ro */
|
||||
#define PCS_STATUS_100BASE_X_HALF_DUPLEX (1<<13) /* ro */
|
||||
#define PCS_STATUS_100BASE_X_FULL_DUPLEX (1<<14) /* ro */
|
||||
#define PCS_STATUS_100BASE_T4 (1<<15) /* ro */
|
||||
|
||||
#define PCS_PHY_IDENTIFIER_0 0x02 /* ro */
|
||||
#define PCS_PHY_IDENTIFIER_1 0x03 /* ro */
|
||||
|
||||
#define PCS_DEV_ABILITY 0x04 /* rw */
|
||||
/* 1000BASE-X */
|
||||
/* Bits 0:4, Reserved. */ /* - */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_FD (1<<5) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_HD (1<<6) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_PS1 (1<<7) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_PS2 (1<<8) /* rw */
|
||||
/* Bits 9:11, Reserved. */ /* - */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_RF1 (1<<12) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_RF2 (1<<13) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_ACK (1<<14) /* rw */
|
||||
#define PCS_DEV_ABILITY_1000BASE_X_NP (1<<15) /* rw */
|
||||
|
||||
#define PCS_PARTNER_ABILITY 0x05 /* ro */
|
||||
/* 1000BASE-X */
|
||||
/* Bits 0:4, Reserved. */ /* - */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_FD (1<<5) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_HD (1<<6) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_PS1 (1<<7) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_PS2 (1<<8) /* ro */
|
||||
/* Bits 9:11, Reserved. */ /* - */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_RF1 (1<<12) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_RF2 (1<<13) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_ACK (1<<14) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_1000BASE_X_NP (1<<15) /* ro */
|
||||
/* SGMII */
|
||||
/* Bits 0:9, Reserved. */ /* - */
|
||||
#define PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED0 (1<<10) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED1 (1<<11) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_SGMII_COPPER_DUPLEX_STATUS (1<<12) /* ro */
|
||||
/* Bit 13, Reserved. */ /* - */
|
||||
#define PCS_PARTNER_ABILITY_SGMII_ACK (1<<14) /* ro */
|
||||
#define PCS_PARTNER_ABILITY_SGMII_COPPER_LINK_STATUS (1<<15) /* ro */
|
||||
|
||||
#define PCS_AN_EXPANSION 0x06 /* ro */
|
||||
#define PCS_AN_EXPANSION_LINK_PARTNER_AUTO_NEGOTIATION_ABLE (1<<0) /* ro */
|
||||
#define PCS_AN_EXPANSION_PAGE_RECEIVE (1<<1) /* ro */
|
||||
#define PCS_AN_EXPANSION_NEXT_PAGE_ABLE (1<<2) /* -, 0 */
|
||||
/* Bits 3:15, Reserved. */ /* - */
|
||||
|
||||
#define PCS_DEVICE_NEXT_PAGE 0x07 /* ro */
|
||||
#define PCS_PARTNER_NEXT_PAGE 0x08 /* ro */
|
||||
#define PCS_MASTER_SLAVE_CNTL 0x09 /* ro */
|
||||
#define PCS_MASTER_SLAVE_STAT 0x0A /* ro */
|
||||
/* 0x0B - 0x0E, Reserved */ /* - */
|
||||
#define PCS_EXTENDED_STATUS 0x0F /* ro */
|
||||
/* Specific Extended Registers. */
|
||||
#define PCS_EXT_SCRATCH 0x10 /* rw */
|
||||
#define PCS_EXT_REV 0x11 /* ro */
|
||||
#define PCS_EXT_LINK_TIMER_0 0x12 /* rw */
|
||||
#define PCS_EXT_LINK_TIMER_1 0x13 /* rw */
|
||||
#define PCS_EXT_IF_MODE 0x14 /* rw */
|
||||
#define PCS_EXT_IF_MODE_SGMII_ENA (1<<0) /* rw */
|
||||
#define PCS_EXT_IF_MODE_USE_SGMII_AN (1<<1) /* rw */
|
||||
#define PCS_EXT_IF_MODE_SGMII_SPEED1 (1<<2) /* rw */
|
||||
#define PCS_EXT_IF_MODE_SGMII_SPEED0 (1<<3) /* rw */
|
||||
#define PCS_EXT_IF_MODE_SGMII_DUPLEX (1<<4) /* rw */
|
||||
/* Bits 5:15, Reserved. */ /* - */
|
||||
|
||||
#define PCS_EXT_DISABLE_READ_TIMEOUT 0x15 /* rw */
|
||||
#define PCS_EXT_READ_TIMEOUT 0x16 /* r0 */
|
||||
/* 0x17-0x1F, Reserved. */
|
||||
|
||||
/* 0xA0 - 0xBF, MDIO Space 1. */
|
||||
#define MDIO_1_START 0xA0
|
||||
#define ATSE_BMCR MDIO_1_START
|
||||
|
||||
/* 0xC0 - 0xC7, Supplementary Address. */
|
||||
#define SUPPL_ADDR_SMAC_0_0 0xC0 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_0_1 0xC1 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_1_0 0xC2 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_1_1 0xC3 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_2_0 0xC4 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_2_1 0xC5 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_3_0 0xC6 /* rw */
|
||||
#define SUPPL_ADDR_SMAC_3_1 0xC7 /* rw */
|
||||
|
||||
/* 0xC8 - 0xCF, Reserved; set to zero, ignore on read. */
|
||||
/* 0xD7 - 0xFF, Reserved; set to zero, ignore on read. */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* DE4 Intel Strata Flash Ethernet Option Bits area. */
|
||||
/* XXX-BZ this is something a loader will have to handle for us. */
|
||||
#define ALTERA_ETHERNET_OPTION_BITS_OFF 0x00008000
|
||||
#define ALTERA_ETHERNET_OPTION_BITS_LEN 0x00007fff
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct atse_softc {
|
||||
if_t atse_ifp;
|
||||
struct resource *atse_mem_res;
|
||||
device_t atse_miibus;
|
||||
device_t atse_dev;
|
||||
int atse_unit;
|
||||
int atse_mem_rid;
|
||||
int atse_phy_addr;
|
||||
int atse_if_flags;
|
||||
bus_addr_t atse_bmcr0;
|
||||
bus_addr_t atse_bmcr1;
|
||||
uint32_t atse_flags;
|
||||
#define ATSE_FLAGS_LINK 0x00000001
|
||||
#define ATSE_FLAGS_ERROR 0x00000002
|
||||
#define ATSE_FLAGS_SOP_SEEN 0x00000004
|
||||
uint8_t atse_eth_addr[ETHER_ADDR_LEN];
|
||||
#define ATSE_ETH_ADDR_DEF 0x01
|
||||
#define ATSE_ETH_ADDR_SUPP1 0x02
|
||||
#define ATSE_ETH_ADDR_SUPP2 0x04
|
||||
#define ATSE_ETH_ADDR_SUPP3 0x08
|
||||
#define ATSE_ETH_ADDR_SUPP4 0x10
|
||||
#define ATSE_ETH_ADDR_ALL 0x1f
|
||||
int16_t atse_rx_cycles; /* POLLING */
|
||||
#define RX_CYCLES_IN_INTR 5
|
||||
uint32_t atse_rx_err[6];
|
||||
#define ATSE_RX_ERR_FIFO_THRES_EOP 0 /* FIFO threshold reached, on EOP. */
|
||||
#define ATSE_RX_ERR_ELEN 1 /* Frame/payload length not valid. */
|
||||
#define ATSE_RX_ERR_CRC32 2 /* CRC-32 error. */
|
||||
#define ATSE_RX_ERR_FIFO_THRES_TRUNC 3 /* FIFO thresh., truncated frame. */
|
||||
#define ATSE_RX_ERR_4 4 /* ? */
|
||||
#define ATSE_RX_ERR_5 5 /* / */
|
||||
#define ATSE_RX_ERR_MAX 6
|
||||
struct callout atse_tick;
|
||||
struct mtx atse_mtx;
|
||||
device_t dev;
|
||||
|
||||
/* xDMA */
|
||||
xdma_controller_t *xdma_tx;
|
||||
xdma_channel_t *xchan_tx;
|
||||
void *ih_tx;
|
||||
int txcount;
|
||||
|
||||
xdma_controller_t *xdma_rx;
|
||||
xdma_channel_t *xchan_rx;
|
||||
void *ih_rx;
|
||||
|
||||
struct buf_ring *br;
|
||||
struct mtx br_mtx;
|
||||
};
|
||||
|
||||
int atse_attach(device_t);
|
||||
int atse_detach_dev(device_t);
|
||||
void atse_detach_resources(device_t);
|
||||
|
||||
int atse_miibus_readreg(device_t, int, int);
|
||||
int atse_miibus_writereg(device_t, int, int, int);
|
||||
void atse_miibus_statchg(device_t);
|
||||
|
||||
#endif /* _DEV_IF_ATSEREG_H */
|
||||
|
|
@ -1,551 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012-2013, 2016 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/altera/avgen/altera_avgen.h>
|
||||
|
||||
/*
|
||||
* Generic device driver for allowing read(), write(), and mmap() on
|
||||
* memory-mapped, Avalon-attached devices. There is no actual dependence on
|
||||
* Avalon, so conceivably this should just be soc_dev or similar, since many
|
||||
* system-on-chip bus environments would work fine with the same code.
|
||||
*/
|
||||
|
||||
static d_mmap_t altera_avgen_mmap;
|
||||
static d_read_t altera_avgen_read;
|
||||
static d_write_t altera_avgen_write;
|
||||
|
||||
#define ALTERA_AVGEN_DEVNAME "altera_avgen"
|
||||
#define ALTERA_AVGEN_DEVNAME_FMT (ALTERA_AVGEN_DEVNAME "%d")
|
||||
|
||||
static struct cdevsw avg_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_mmap = altera_avgen_mmap,
|
||||
.d_read = altera_avgen_read,
|
||||
.d_write = altera_avgen_write,
|
||||
.d_name = ALTERA_AVGEN_DEVNAME,
|
||||
};
|
||||
|
||||
#define ALTERA_AVGEN_SECTORSIZE 512 /* Not configurable at this time. */
|
||||
|
||||
static int
|
||||
altera_avgen_read(struct cdev *dev, struct uio *uio, int flag)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
u_long offset, size;
|
||||
#ifdef NOTYET
|
||||
uint64_t v8;
|
||||
#endif
|
||||
uint32_t v4;
|
||||
uint16_t v2;
|
||||
uint8_t v1;
|
||||
u_int width;
|
||||
int error;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
if ((sc->avg_flags & ALTERA_AVALON_FLAG_READ) == 0)
|
||||
return (EACCES);
|
||||
width = sc->avg_width;
|
||||
if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
|
||||
uio->uio_resid % width != 0)
|
||||
return (ENODEV);
|
||||
size = rman_get_size(sc->avg_res);
|
||||
if ((uio->uio_offset + uio->uio_resid < 0) ||
|
||||
(uio->uio_offset + uio->uio_resid > size))
|
||||
return (ENODEV);
|
||||
while (uio->uio_resid > 0) {
|
||||
offset = uio->uio_offset;
|
||||
if (offset + width > size)
|
||||
return (ENODEV);
|
||||
switch (width) {
|
||||
case 1:
|
||||
v1 = bus_read_1(sc->avg_res, offset);
|
||||
error = uiomove(&v1, sizeof(v1), uio);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
v2 = bus_read_2(sc->avg_res, offset);
|
||||
error = uiomove(&v2, sizeof(v2), uio);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
v4 = bus_read_4(sc->avg_res, offset);
|
||||
error = uiomove(&v4, sizeof(v4), uio);
|
||||
break;
|
||||
|
||||
#ifdef NOTYET
|
||||
case 8:
|
||||
v8 = bus_read_8(sc->avg_res, offset);
|
||||
error = uiomove(&v8, sizeof(v8), uio);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
panic("%s: unexpected widthment %u", __func__, width);
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_write(struct cdev *dev, struct uio *uio, int flag)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
u_long offset, size;
|
||||
#ifdef NOTYET
|
||||
uint64_t v8;
|
||||
#endif
|
||||
uint32_t v4;
|
||||
uint16_t v2;
|
||||
uint8_t v1;
|
||||
u_int width;
|
||||
int error;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
if ((sc->avg_flags & ALTERA_AVALON_FLAG_WRITE) == 0)
|
||||
return (EACCES);
|
||||
width = sc->avg_width;
|
||||
if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
|
||||
uio->uio_resid % width != 0)
|
||||
return (ENODEV);
|
||||
size = rman_get_size(sc->avg_res);
|
||||
while (uio->uio_resid > 0) {
|
||||
offset = uio->uio_offset;
|
||||
if (offset + width > size)
|
||||
return (ENODEV);
|
||||
switch (width) {
|
||||
case 1:
|
||||
error = uiomove(&v1, sizeof(v1), uio);
|
||||
if (error)
|
||||
return (error);
|
||||
bus_write_1(sc->avg_res, offset, v1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
error = uiomove(&v2, sizeof(v2), uio);
|
||||
if (error)
|
||||
return (error);
|
||||
bus_write_2(sc->avg_res, offset, v2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
error = uiomove(&v4, sizeof(v4), uio);
|
||||
if (error)
|
||||
return (error);
|
||||
bus_write_4(sc->avg_res, offset, v4);
|
||||
break;
|
||||
|
||||
#ifdef NOTYET
|
||||
case 8:
|
||||
error = uiomove(&v8, sizeof(v8), uio);
|
||||
if (error)
|
||||
return (error);
|
||||
bus_write_8(sc->avg_res, offset, v8);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
panic("%s: unexpected width %u", __func__, width);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
|
||||
int nprot, vm_memattr_t *memattr)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
if (nprot & VM_PROT_READ) {
|
||||
if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_READ) == 0)
|
||||
return (EACCES);
|
||||
}
|
||||
if (nprot & VM_PROT_WRITE) {
|
||||
if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_WRITE) == 0)
|
||||
return (EACCES);
|
||||
}
|
||||
if (nprot & VM_PROT_EXECUTE) {
|
||||
if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_EXEC) == 0)
|
||||
return (EACCES);
|
||||
}
|
||||
if (trunc_page(offset) == offset &&
|
||||
offset + PAGE_SIZE > offset &&
|
||||
rman_get_size(sc->avg_res) >= offset + PAGE_SIZE) {
|
||||
*paddr = rman_get_start(sc->avg_res) + offset;
|
||||
*memattr = VM_MEMATTR_UNCACHEABLE;
|
||||
} else
|
||||
return (ENODEV);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: We serialise block reads and writes in case the OS is generating
|
||||
* concurrent I/O against the same block, in which case we want one I/O (or
|
||||
* another) to win. This is not sufficient to provide atomicity for the
|
||||
* sector in the presence of a fail stop -- however, we're just writing this
|
||||
* to non-persistent DRAM .. right?
|
||||
*/
|
||||
static void
|
||||
altera_avgen_disk_strategy(struct bio *bp)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
void *data;
|
||||
long bcount;
|
||||
daddr_t pblkno;
|
||||
int error;
|
||||
|
||||
sc = bp->bio_disk->d_drv1;
|
||||
data = bp->bio_data;
|
||||
bcount = bp->bio_bcount;
|
||||
pblkno = bp->bio_pblkno;
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
* Serialize block reads / writes.
|
||||
*/
|
||||
mtx_lock(&sc->avg_disk_mtx);
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
if (!(sc->avg_flags & ALTERA_AVALON_FLAG_GEOM_READ)) {
|
||||
error = EROFS;
|
||||
break;
|
||||
}
|
||||
switch (sc->avg_width) {
|
||||
case 1:
|
||||
bus_read_region_1(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint8_t *)data, bcount);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bus_read_region_2(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint16_t *)data, bcount / 2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
bus_read_region_4(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint32_t *)data, bcount / 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: unexpected width %u", __func__,
|
||||
sc->avg_width);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_WRITE:
|
||||
if (!(sc->avg_flags & ALTERA_AVALON_FLAG_GEOM_WRITE)) {
|
||||
biofinish(bp, NULL, EROFS);
|
||||
break;
|
||||
}
|
||||
switch (sc->avg_width) {
|
||||
case 1:
|
||||
bus_write_region_1(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint8_t *)data, bcount);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bus_write_region_2(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint16_t *)data, bcount / 2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
bus_write_region_4(sc->avg_res,
|
||||
bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE,
|
||||
(uint32_t *)data, bcount / 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: unexpected width %u", __func__,
|
||||
sc->avg_width);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&sc->avg_disk_mtx);
|
||||
biofinish(bp, NULL, error);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_process_options(struct altera_avgen_softc *sc,
|
||||
const char *str_fileio, const char *str_geomio, const char *str_mmapio,
|
||||
const char *str_devname, int devunit)
|
||||
{
|
||||
const char *cp;
|
||||
device_t dev = sc->avg_dev;
|
||||
|
||||
/*
|
||||
* Check for valid combinations of options.
|
||||
*/
|
||||
if (str_fileio == NULL && str_geomio == NULL && str_mmapio == NULL) {
|
||||
device_printf(dev,
|
||||
"at least one of %s, %s, or %s must be specified\n",
|
||||
ALTERA_AVALON_STR_FILEIO, ALTERA_AVALON_STR_GEOMIO,
|
||||
ALTERA_AVALON_STR_MMAPIO);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validity check: a device can either be a GEOM device (in which case
|
||||
* we use GEOM to register the device node), or a special device --
|
||||
* but not both as that causes a collision in /dev.
|
||||
*/
|
||||
if (str_geomio != NULL && (str_fileio != NULL || str_mmapio != NULL)) {
|
||||
device_printf(dev,
|
||||
"at most one of %s and (%s or %s) may be specified\n",
|
||||
ALTERA_AVALON_STR_GEOMIO, ALTERA_AVALON_STR_FILEIO,
|
||||
ALTERA_AVALON_STR_MMAPIO);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that a unit is specified if a name is also specified.
|
||||
*/
|
||||
if (str_devname == NULL && devunit != -1) {
|
||||
device_printf(dev, "%s requires %s be specified\n",
|
||||
ALTERA_AVALON_STR_DEVUNIT, ALTERA_AVALON_STR_DEVNAME);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract, digest, and save values.
|
||||
*/
|
||||
switch (sc->avg_width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
#ifdef NOTYET
|
||||
case 8:
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(dev, "%s unsupported value %u\n",
|
||||
ALTERA_AVALON_STR_WIDTH, sc->avg_width);
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->avg_flags = 0;
|
||||
if (str_fileio != NULL) {
|
||||
for (cp = str_fileio; *cp != '\0'; cp++) {
|
||||
switch (*cp) {
|
||||
case ALTERA_AVALON_CHAR_READ:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_READ;
|
||||
break;
|
||||
|
||||
case ALTERA_AVALON_CHAR_WRITE:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_WRITE;
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(dev,
|
||||
"invalid %s character %c\n",
|
||||
ALTERA_AVALON_STR_FILEIO, *cp);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (str_geomio != NULL) {
|
||||
for (cp = str_geomio; *cp != '\0'; cp++){
|
||||
switch (*cp) {
|
||||
case ALTERA_AVALON_CHAR_READ:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_GEOM_READ;
|
||||
break;
|
||||
|
||||
case ALTERA_AVALON_CHAR_WRITE:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_GEOM_WRITE;
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(dev,
|
||||
"invalid %s character %c\n",
|
||||
ALTERA_AVALON_STR_GEOMIO, *cp);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (str_mmapio != NULL) {
|
||||
for (cp = str_mmapio; *cp != '\0'; cp++) {
|
||||
switch (*cp) {
|
||||
case ALTERA_AVALON_CHAR_READ:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_READ;
|
||||
break;
|
||||
|
||||
case ALTERA_AVALON_CHAR_WRITE:
|
||||
sc->avg_flags |=
|
||||
ALTERA_AVALON_FLAG_MMAP_WRITE;
|
||||
break;
|
||||
|
||||
case ALTERA_AVALON_CHAR_EXEC:
|
||||
sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_EXEC;
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(dev,
|
||||
"invalid %s character %c\n",
|
||||
ALTERA_AVALON_STR_MMAPIO, *cp);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio,
|
||||
const char *str_geomio, const char *str_mmapio, const char *str_devname,
|
||||
int devunit)
|
||||
{
|
||||
device_t dev = sc->avg_dev;
|
||||
int error;
|
||||
|
||||
error = altera_avgen_process_options(sc, str_fileio, str_geomio,
|
||||
str_mmapio, str_devname, devunit);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
|
||||
if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
|
||||
device_printf(dev,
|
||||
"memory region not even multiple of page size\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
|
||||
device_printf(dev, "memory region not page-aligned\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a GEOM permission is requested, then create the device via GEOM.
|
||||
* Otherwise, create a special device. We checked during options
|
||||
* processing that both weren't requested a once.
|
||||
*/
|
||||
if (str_devname != NULL) {
|
||||
sc->avg_name = strdup(str_devname, M_TEMP);
|
||||
devunit = sc->avg_unit;
|
||||
} else
|
||||
sc->avg_name = strdup(ALTERA_AVGEN_DEVNAME, M_TEMP);
|
||||
if (sc->avg_flags & (ALTERA_AVALON_FLAG_GEOM_READ |
|
||||
ALTERA_AVALON_FLAG_GEOM_WRITE)) {
|
||||
mtx_init(&sc->avg_disk_mtx, "altera_avgen_disk", NULL,
|
||||
MTX_DEF);
|
||||
sc->avg_disk = disk_alloc();
|
||||
sc->avg_disk->d_drv1 = sc;
|
||||
sc->avg_disk->d_strategy = altera_avgen_disk_strategy;
|
||||
if (devunit == -1)
|
||||
devunit = 0;
|
||||
sc->avg_disk->d_name = sc->avg_name;
|
||||
sc->avg_disk->d_unit = devunit;
|
||||
|
||||
/*
|
||||
* NB: As avg_res is a multiple of PAGE_SIZE, it is also a
|
||||
* multiple of ALTERA_AVGEN_SECTORSIZE.
|
||||
*/
|
||||
sc->avg_disk->d_sectorsize = ALTERA_AVGEN_SECTORSIZE;
|
||||
sc->avg_disk->d_mediasize = rman_get_size(sc->avg_res);
|
||||
sc->avg_disk->d_maxsize = ALTERA_AVGEN_SECTORSIZE;
|
||||
disk_create(sc->avg_disk, DISK_VERSION);
|
||||
} else {
|
||||
/* Device node allocation. */
|
||||
if (str_devname == NULL) {
|
||||
str_devname = ALTERA_AVGEN_DEVNAME_FMT;
|
||||
devunit = sc->avg_unit;
|
||||
}
|
||||
if (devunit != -1)
|
||||
sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit,
|
||||
UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR, "%s%d",
|
||||
str_devname, devunit);
|
||||
else
|
||||
sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit,
|
||||
UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR,
|
||||
"%s", str_devname);
|
||||
if (sc->avg_cdev == NULL) {
|
||||
device_printf(sc->avg_dev, "%s: make_dev failed\n",
|
||||
__func__);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* XXXRW: Slight race between make_dev(9) and here. */
|
||||
sc->avg_cdev->si_drv1 = sc;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
altera_avgen_detach(struct altera_avgen_softc *sc)
|
||||
{
|
||||
|
||||
KASSERT((sc->avg_disk != NULL) || (sc->avg_cdev != NULL),
|
||||
("%s: neither GEOM nor special device", __func__));
|
||||
|
||||
if (sc->avg_disk != NULL) {
|
||||
disk_gone(sc->avg_disk);
|
||||
disk_destroy(sc->avg_disk);
|
||||
free(sc->avg_name, M_TEMP);
|
||||
mtx_destroy(&sc->avg_disk_mtx);
|
||||
} else {
|
||||
destroy_dev(sc->avg_cdev);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012, 2016 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ALTERA_AVALON_H_
|
||||
#define _DEV_ALTERA_AVALON_H_
|
||||
|
||||
struct altera_avgen_softc {
|
||||
/*
|
||||
* Bus-related fields.
|
||||
*/
|
||||
device_t avg_dev;
|
||||
int avg_unit;
|
||||
char *avg_name;
|
||||
|
||||
/*
|
||||
* The device node and memory-mapped I/O region.
|
||||
*/
|
||||
struct cdev *avg_cdev;
|
||||
struct resource *avg_res;
|
||||
int avg_rid;
|
||||
|
||||
/*
|
||||
* Access properties configured by device.hints.
|
||||
*/
|
||||
u_int avg_flags;
|
||||
u_int avg_width;
|
||||
u_int avg_sectorsize;
|
||||
|
||||
/*
|
||||
* disk(9) state, if required for this device.
|
||||
*/
|
||||
struct disk *avg_disk;
|
||||
struct mtx avg_disk_mtx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Various flags extracted from device.hints to configure operations on the
|
||||
* device.
|
||||
*/
|
||||
#define ALTERA_AVALON_FLAG_READ 0x01
|
||||
#define ALTERA_AVALON_FLAG_WRITE 0x02
|
||||
#define ALTERA_AVALON_FLAG_MMAP_READ 0x04
|
||||
#define ALTERA_AVALON_FLAG_MMAP_WRITE 0x08
|
||||
#define ALTERA_AVALON_FLAG_MMAP_EXEC 0x10
|
||||
#define ALTERA_AVALON_FLAG_GEOM_READ 0x20
|
||||
#define ALTERA_AVALON_FLAG_GEOM_WRITE 0x40
|
||||
|
||||
#define ALTERA_AVALON_CHAR_READ 'r'
|
||||
#define ALTERA_AVALON_CHAR_WRITE 'w'
|
||||
#define ALTERA_AVALON_CHAR_EXEC 'x'
|
||||
|
||||
#define ALTERA_AVALON_STR_WIDTH "width"
|
||||
#define ALTERA_AVALON_STR_FILEIO "fileio"
|
||||
#define ALTERA_AVALON_STR_GEOMIO "geomio"
|
||||
#define ALTERA_AVALON_STR_MMAPIO "mmapio"
|
||||
#define ALTERA_AVALON_STR_DEVNAME "devname"
|
||||
#define ALTERA_AVALON_STR_DEVUNIT "devunit"
|
||||
|
||||
/*
|
||||
* Driver setup routines from the bus attachment/teardown.
|
||||
*/
|
||||
int altera_avgen_attach(struct altera_avgen_softc *sc,
|
||||
const char *str_fileio, const char *str_geomio,
|
||||
const char *str_mmapio, const char *str_devname, int devunit);
|
||||
void altera_avgen_detach(struct altera_avgen_softc *sc);
|
||||
|
||||
#endif /* _DEV_ALTERA_AVALON_H_ */
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012-2013, 2016 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/altera/avgen/altera_avgen.h>
|
||||
|
||||
static int
|
||||
altera_avgen_fdt_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "sri-cambridge,avgen")) {
|
||||
device_set_desc(dev, "Generic Altera Avalon device attachment");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_fdt_attach(device_t dev)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
char *str_fileio, *str_geomio, *str_mmapio;
|
||||
char *str_devname;
|
||||
phandle_t node;
|
||||
pcell_t cell;
|
||||
int devunit, error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->avg_dev = dev;
|
||||
sc->avg_unit = device_get_unit(dev);
|
||||
|
||||
/*
|
||||
* Query driver-specific OpenFirmware properties to determine how to
|
||||
* expose the device via /dev.
|
||||
*/
|
||||
str_fileio = NULL;
|
||||
str_geomio = NULL;
|
||||
str_mmapio = NULL;
|
||||
str_devname = NULL;
|
||||
devunit = -1;
|
||||
sc->avg_width = 1;
|
||||
node = ofw_bus_get_node(dev);
|
||||
if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0)
|
||||
sc->avg_width = cell;
|
||||
(void)OF_getprop_alloc(node, "sri-cambridge,fileio",
|
||||
(void **)&str_fileio);
|
||||
(void)OF_getprop_alloc(node, "sri-cambridge,geomio",
|
||||
(void **)&str_geomio);
|
||||
(void)OF_getprop_alloc(node, "sri-cambridge,mmapio",
|
||||
(void **)&str_mmapio);
|
||||
(void)OF_getprop_alloc(node, "sri-cambridge,devname",
|
||||
(void **)&str_devname);
|
||||
if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0)
|
||||
devunit = cell;
|
||||
|
||||
/* Memory allocation and checking. */
|
||||
sc->avg_rid = 0;
|
||||
sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->avg_rid, RF_ACTIVE);
|
||||
if (sc->avg_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
error = altera_avgen_attach(sc, str_fileio, str_geomio, str_mmapio,
|
||||
str_devname, devunit);
|
||||
if (error != 0)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
|
||||
sc->avg_res);
|
||||
if (str_fileio != NULL)
|
||||
OF_prop_free(str_fileio);
|
||||
if (str_geomio != NULL)
|
||||
OF_prop_free(str_geomio);
|
||||
if (str_mmapio != NULL)
|
||||
OF_prop_free(str_mmapio);
|
||||
if (str_devname != NULL)
|
||||
OF_prop_free(str_devname);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_fdt_detach(device_t dev)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
altera_avgen_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_avgen_fdt_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_avgen_fdt_probe),
|
||||
DEVMETHOD(device_attach, altera_avgen_fdt_attach),
|
||||
DEVMETHOD(device_detach, altera_avgen_fdt_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_avgen_fdt_driver = {
|
||||
"altera_avgen",
|
||||
altera_avgen_fdt_methods,
|
||||
sizeof(struct altera_avgen_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(avgen, simplebus, altera_avgen_fdt_driver, 0, 0);
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012-2013, 2016 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/altera/avgen/altera_avgen.h>
|
||||
|
||||
static int
|
||||
altera_avgen_nexus_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "Generic Altera Avalon device attachment");
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_nexus_attach(device_t dev)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
const char *str_fileio, *str_geomio, *str_mmapio;
|
||||
const char *str_devname;
|
||||
int devunit, error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->avg_dev = dev;
|
||||
sc->avg_unit = device_get_unit(dev);
|
||||
|
||||
/*
|
||||
* Query non-standard hints to find out what operations are permitted
|
||||
* on the device, and whether it is cached.
|
||||
*/
|
||||
str_fileio = NULL;
|
||||
str_geomio = NULL;
|
||||
str_mmapio = NULL;
|
||||
str_devname = NULL;
|
||||
devunit = -1;
|
||||
sc->avg_width = 1;
|
||||
error = resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
|
||||
if (error != 0 && error != ENOENT) {
|
||||
device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
|
||||
return (error);
|
||||
}
|
||||
(void)resource_string_value(device_get_name(dev),
|
||||
device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
|
||||
(void)resource_string_value(device_get_name(dev),
|
||||
device_get_unit(dev), ALTERA_AVALON_STR_GEOMIO, &str_geomio);
|
||||
(void)resource_string_value(device_get_name(dev),
|
||||
device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
|
||||
(void)resource_string_value(device_get_name(dev),
|
||||
device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
|
||||
(void)resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
ALTERA_AVALON_STR_DEVUNIT, &devunit);
|
||||
|
||||
/* Memory allocation and checking. */
|
||||
sc->avg_rid = 0;
|
||||
sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->avg_rid, RF_ACTIVE);
|
||||
if (sc->avg_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
error = altera_avgen_attach(sc, str_fileio, str_geomio, str_mmapio,
|
||||
str_devname, devunit);
|
||||
if (error != 0)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
|
||||
sc->avg_res);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_avgen_nexus_detach(device_t dev)
|
||||
{
|
||||
struct altera_avgen_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
altera_avgen_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_avgen_nexus_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_avgen_nexus_probe),
|
||||
DEVMETHOD(device_attach, altera_avgen_nexus_attach),
|
||||
DEVMETHOD(device_detach, altera_avgen_nexus_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_avgen_nexus_driver = {
|
||||
"altera_avgen",
|
||||
altera_avgen_nexus_methods,
|
||||
sizeof(struct altera_avgen_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, 0, 0);
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2011-2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ALTERA_JTAG_UART_H_
|
||||
#define _DEV_ALTERA_JTAG_UART_H_
|
||||
|
||||
struct altera_jtag_uart_softc {
|
||||
device_t ajus_dev;
|
||||
int ajus_unit;
|
||||
|
||||
/*
|
||||
* Hardware resources.
|
||||
*/
|
||||
struct resource *ajus_irq_res;
|
||||
int ajus_irq_rid;
|
||||
void *ajus_irq_cookie;
|
||||
struct resource *ajus_mem_res;
|
||||
int ajus_mem_rid;
|
||||
|
||||
/*
|
||||
* TTY resources.
|
||||
*/
|
||||
struct tty *ajus_ttyp;
|
||||
int ajus_alt_break_state;
|
||||
|
||||
/*
|
||||
* Driver resources.
|
||||
*/
|
||||
u_int ajus_flags;
|
||||
struct mtx *ajus_lockp;
|
||||
struct mtx ajus_lock;
|
||||
struct callout ajus_io_callout;
|
||||
struct callout ajus_ac_callout;
|
||||
|
||||
/*
|
||||
* One-character buffer required because it's not possible to peek at
|
||||
* the input FIFO without reading it.
|
||||
*/
|
||||
int ajus_buffer_valid;
|
||||
int *ajus_buffer_validp;
|
||||
uint8_t ajus_buffer_data;
|
||||
uint8_t *ajus_buffer_datap;
|
||||
int ajus_jtag_present;
|
||||
int *ajus_jtag_presentp;
|
||||
u_int ajus_jtag_missed;
|
||||
u_int *ajus_jtag_missedp;
|
||||
};
|
||||
|
||||
#define AJU_TTYNAME "ttyj"
|
||||
|
||||
/*
|
||||
* Flag values for ajus_flags.
|
||||
*/
|
||||
#define ALTERA_JTAG_UART_FLAG_CONSOLE 0x00000001 /* Is console. */
|
||||
|
||||
/*
|
||||
* Because tty-level use of the I/O ports completes with low-level console
|
||||
* use, spinlocks must be employed here.
|
||||
*/
|
||||
#define AJU_CONSOLE_LOCK_INIT() do { \
|
||||
mtx_init(&aju_cons_lock, "aju_cons_lock", NULL, MTX_SPIN); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_CONSOLE_LOCK() do { \
|
||||
if (!kdb_active) \
|
||||
mtx_lock_spin(&aju_cons_lock); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_CONSOLE_LOCK_ASSERT() { \
|
||||
if (!kdb_active) \
|
||||
mtx_assert(&aju_cons_lock, MA_OWNED); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_CONSOLE_UNLOCK() do { \
|
||||
if (!kdb_active) \
|
||||
mtx_unlock_spin(&aju_cons_lock); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_LOCK_INIT(sc) do { \
|
||||
mtx_init(&(sc)->ajus_lock, "aju_lock", NULL, MTX_SPIN); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_LOCK_DESTROY(sc) do { \
|
||||
mtx_destroy(&(sc)->ajus_lock); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_LOCK(sc) do { \
|
||||
mtx_lock_spin((sc)->ajus_lockp); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_LOCK_ASSERT(sc) do { \
|
||||
mtx_assert((sc)->ajus_lockp, MA_OWNED); \
|
||||
} while (0)
|
||||
|
||||
#define AJU_UNLOCK(sc) do { \
|
||||
mtx_unlock_spin((sc)->ajus_lockp); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* When a TTY-level Altera JTAG UART instance is also the low-level console,
|
||||
* the TTY layer borrows the console-layer lock and buffer rather than using
|
||||
* its own.
|
||||
*/
|
||||
extern struct mtx aju_cons_lock;
|
||||
extern char aju_cons_buffer_data;
|
||||
extern int aju_cons_buffer_valid;
|
||||
extern int aju_cons_jtag_present;
|
||||
extern u_int aju_cons_jtag_missed;
|
||||
|
||||
/*
|
||||
* Base physical address of the JTAG UART in BERI.
|
||||
*/
|
||||
#define BERI_UART_BASE 0x7f000000 /* JTAG UART */
|
||||
|
||||
/*-
|
||||
* Routines for interacting with the BERI console JTAG UART. Programming
|
||||
* details from the June 2011 "Embedded Peripherals User Guide" by Altera
|
||||
* Corporation, tables 6-2 (JTAG UART Core Register Map), 6-3 (Data Register
|
||||
* Bits), and 6-4 (Control Register Bits).
|
||||
*
|
||||
* Offsets of data and control registers relative to the base. Altera
|
||||
* conventions are maintained in BERI.
|
||||
*/
|
||||
#define ALTERA_JTAG_UART_DATA_OFF 0x00000000
|
||||
#define ALTERA_JTAG_UART_CONTROL_OFF 0x00000004
|
||||
|
||||
/*
|
||||
* Offset 0: 'data' register -- bits 31-16 (RAVAIL), 15 (RVALID),
|
||||
* 14-8 (Reserved), 7-0 (DATA).
|
||||
*
|
||||
* DATA - One byte read or written.
|
||||
* RAVAIL - Bytes available to read (excluding the current byte).
|
||||
* RVALID - Whether the byte in DATA is valid.
|
||||
*/
|
||||
#define ALTERA_JTAG_UART_DATA_DATA 0x000000ff
|
||||
#define ALTERA_JTAG_UART_DATA_RESERVED 0x00007f00
|
||||
#define ALTERA_JTAG_UART_DATA_RVALID 0x00008000
|
||||
#define ALTERA_JTAG_UART_DATA_RAVAIL 0xffff0000
|
||||
#define ALTERA_JTAG_UART_DATA_RAVAIL_SHIFT 16
|
||||
|
||||
/*-
|
||||
* Offset 1: 'control' register -- bits 31-16 (WSPACE), 15-11 (Reserved),
|
||||
* 10 (AC), 9 (WI), 8 (RI), 7..2 (Reserved), 1 (WE), 0 (RE).
|
||||
*
|
||||
* RE - Enable read interrupts.
|
||||
* WE - Enable write interrupts.
|
||||
* RI - Read interrupt pending.
|
||||
* WI - Write interrupt pending.
|
||||
* AC - Activity bit; set to '1' to clear to '0'.
|
||||
* WSPACE - Space available in the write FIFO.
|
||||
*/
|
||||
#define ALTERA_JTAG_UART_CONTROL_RE 0x00000001
|
||||
#define ALTERA_JTAG_UART_CONTROL_WE 0x00000002
|
||||
#define ALTERA_JTAG_UART_CONTROL_RESERVED0 0x000000fc
|
||||
#define ALTERA_JTAG_UART_CONTROL_RI 0x00000100
|
||||
#define ALTERA_JTAG_UART_CONTROL_WI 0x00000200
|
||||
#define ALTERA_JTAG_UART_CONTROL_AC 0x00000400
|
||||
#define ALTERA_JTAG_UART_CONTROL_RESERVED1 0x0000f800
|
||||
#define ALTERA_JTAG_UART_CONTROL_WSPACE 0xffff0000
|
||||
#define ALTERA_JTAG_UART_CONTROL_WSPACE_SHIFT 16
|
||||
|
||||
/*
|
||||
* Driver attachment functions for Nexus.
|
||||
*/
|
||||
int altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc);
|
||||
void altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc);
|
||||
|
||||
#endif /* _DEV_ALTERA_JTAG_UART_H_ */
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2011-2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/tty.h>
|
||||
|
||||
#include <ddb/ddb.h>
|
||||
|
||||
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
|
||||
|
||||
static SYSCTL_NODE(_hw, OID_AUTO, altera_jtag_uart,
|
||||
CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
||||
"Altera JTAG UART configuration knobs");
|
||||
|
||||
/*
|
||||
* One-byte buffer as we can't check whether the UART is readable without
|
||||
* actually reading from it, synchronised by a spinlock; this lock also
|
||||
* synchronises access to the I/O ports for non-atomic sequences. These
|
||||
* symbols are public so that the TTY layer can use them when working on an
|
||||
* instance of the UART that is also a low-level console.
|
||||
*/
|
||||
char aju_cons_buffer_data;
|
||||
int aju_cons_buffer_valid;
|
||||
int aju_cons_jtag_present;
|
||||
u_int aju_cons_jtag_missed;
|
||||
struct mtx aju_cons_lock;
|
||||
|
||||
/*
|
||||
* Low-level console driver functions.
|
||||
*/
|
||||
static cn_probe_t aju_cnprobe;
|
||||
static cn_init_t aju_cninit;
|
||||
static cn_term_t aju_cnterm;
|
||||
static cn_getc_t aju_cngetc;
|
||||
static cn_putc_t aju_cnputc;
|
||||
static cn_grab_t aju_cngrab;
|
||||
static cn_ungrab_t aju_cnungrab;
|
||||
|
||||
/*
|
||||
* JTAG sets the ALTERA_JTAG_UART_CONTROL_AC bit whenever it accesses the
|
||||
* FIFO. This allows us to (sort of) tell when JTAG is present, so that we
|
||||
* can adopt lossy, rather than blocking, behaviour when JTAG isn't there.
|
||||
* When it is present, we do full flow control. This delay is how long we
|
||||
* wait to see if JTAG has really disappeared when finding a full buffer and
|
||||
* no AC bit set.
|
||||
*/
|
||||
#define ALTERA_JTAG_UART_AC_POLL_DELAY 10000
|
||||
static u_int altera_jtag_uart_ac_poll_delay =
|
||||
ALTERA_JTAG_UART_AC_POLL_DELAY;
|
||||
SYSCTL_UINT(_hw_altera_jtag_uart, OID_AUTO, ac_poll_delay,
|
||||
CTLFLAG_RW, &altera_jtag_uart_ac_poll_delay, 0,
|
||||
"Maximum delay waiting for JTAG present flag when buffer is full");
|
||||
|
||||
/*
|
||||
* I/O routines lifted from Deimos. This is not only MIPS-specific, but also
|
||||
* BERI-specific, as we're hard coding the address at which we expect to
|
||||
* find the Altera JTAG UART and using it unconditionally. We use these
|
||||
* low-level routines so that we can perform console I/O long before newbus
|
||||
* has initialised and devices have attached. The TTY layer of the driver
|
||||
* knows about this, and uses the console-layer spinlock instead of the
|
||||
* TTY-layer lock to avoid confusion between layers for the console UART.
|
||||
*
|
||||
* XXXRW: The only place this inter-layer behaviour breaks down is if the
|
||||
* low-level console is used for polled read while the TTY driver is also
|
||||
* looking for input. Probably we should also share buffers between layers.
|
||||
*/
|
||||
#define MIPS_XKPHYS_UNCACHED_BASE 0x9000000000000000
|
||||
|
||||
typedef uint64_t paddr_t;
|
||||
typedef uint64_t vaddr_t;
|
||||
|
||||
static inline vaddr_t
|
||||
mips_phys_to_uncached(paddr_t phys)
|
||||
{
|
||||
|
||||
return (phys | MIPS_XKPHYS_UNCACHED_BASE);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
mips_ioread_uint32(vaddr_t vaddr)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
__asm__ __volatile__ ("lw %0, 0(%1)" : "=r" (v) : "r" (vaddr));
|
||||
return (v);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mips_iowrite_uint32(vaddr_t vaddr, uint32_t v)
|
||||
{
|
||||
|
||||
__asm__ __volatile__ ("sw %0, 0(%1)" : : "r" (v), "r" (vaddr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Little-endian versions of 32-bit I/O routines.
|
||||
*/
|
||||
static inline uint32_t
|
||||
mips_ioread_uint32le(vaddr_t vaddr)
|
||||
{
|
||||
|
||||
return (le32toh(mips_ioread_uint32(vaddr)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
mips_iowrite_uint32le(vaddr_t vaddr, uint32_t v)
|
||||
{
|
||||
|
||||
mips_iowrite_uint32(vaddr, htole32(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level read and write register routines; the Altera UART is little
|
||||
* endian, so we byte swap 32-bit reads and writes.
|
||||
*/
|
||||
static inline uint32_t
|
||||
aju_cons_data_read(void)
|
||||
{
|
||||
|
||||
return (mips_ioread_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
|
||||
ALTERA_JTAG_UART_DATA_OFF)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
aju_cons_data_write(uint32_t v)
|
||||
{
|
||||
|
||||
mips_iowrite_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
|
||||
ALTERA_JTAG_UART_DATA_OFF), v);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
aju_cons_control_read(void)
|
||||
{
|
||||
|
||||
return (mips_ioread_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
|
||||
ALTERA_JTAG_UART_CONTROL_OFF)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
aju_cons_control_write(uint32_t v)
|
||||
{
|
||||
|
||||
mips_iowrite_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
|
||||
ALTERA_JTAG_UART_CONTROL_OFF), v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Slightly higher-level routines aware of buffering and flow control.
|
||||
*/
|
||||
static int
|
||||
aju_cons_readable(void)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_CONSOLE_LOCK_ASSERT();
|
||||
|
||||
if (aju_cons_buffer_valid)
|
||||
return (1);
|
||||
v = aju_cons_data_read();
|
||||
if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
|
||||
aju_cons_buffer_valid = 1;
|
||||
aju_cons_buffer_data = (v & ALTERA_JTAG_UART_DATA_DATA);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cons_write(char ch)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_CONSOLE_LOCK_ASSERT();
|
||||
|
||||
/*
|
||||
* The flow control logic here is somewhat subtle: we want to wait for
|
||||
* write buffer space only while JTAG is present. However, we can't
|
||||
* directly ask if JTAG is present -- just whether it's been seen
|
||||
* since we last cleared the ALTERA_JTAG_UART_CONTROL_AC bit. As
|
||||
* such, implement a polling loop in which we both wait for space and
|
||||
* try to decide whether JTAG has disappeared on us. We will have to
|
||||
* wait one complete polling delay to detect that JTAG has gone away,
|
||||
* but otherwise shouldn't wait any further once it has gone. And we
|
||||
* had to wait for buffer space anyway, if it was there.
|
||||
*
|
||||
* If JTAG is spotted, reset the TTY-layer miss counter so console-
|
||||
* layer clearing of the bit doesn't trigger a TTY-layer
|
||||
* disconnection.
|
||||
*
|
||||
* XXXRW: Notice the inherent race with hardware: in clearing the
|
||||
* bit, we may race with hardware setting the same bit. This can
|
||||
* cause real-world reliability problems due to lost output on the
|
||||
* console.
|
||||
*/
|
||||
v = aju_cons_control_read();
|
||||
if (v & ALTERA_JTAG_UART_CONTROL_AC) {
|
||||
aju_cons_jtag_present = 1;
|
||||
aju_cons_jtag_missed = 0;
|
||||
v &= ~ALTERA_JTAG_UART_CONTROL_AC;
|
||||
aju_cons_control_write(v);
|
||||
}
|
||||
while ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) == 0) {
|
||||
if (!aju_cons_jtag_present)
|
||||
return;
|
||||
DELAY(altera_jtag_uart_ac_poll_delay);
|
||||
v = aju_cons_control_read();
|
||||
if (v & ALTERA_JTAG_UART_CONTROL_AC) {
|
||||
aju_cons_jtag_present = 1;
|
||||
v &= ~ALTERA_JTAG_UART_CONTROL_AC;
|
||||
aju_cons_control_write(v);
|
||||
} else
|
||||
aju_cons_jtag_present = 0;
|
||||
}
|
||||
aju_cons_data_write(ch);
|
||||
}
|
||||
|
||||
static char
|
||||
aju_cons_read(void)
|
||||
{
|
||||
|
||||
AJU_CONSOLE_LOCK_ASSERT();
|
||||
|
||||
while (!aju_cons_readable());
|
||||
aju_cons_buffer_valid = 0;
|
||||
return (aju_cons_buffer_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of a FreeBSD low-level, polled console driver.
|
||||
*/
|
||||
static void
|
||||
aju_cnprobe(struct consdev *cp)
|
||||
{
|
||||
|
||||
sprintf(cp->cn_name, "%s%d", AJU_TTYNAME, 0);
|
||||
cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cninit(struct consdev *cp)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_CONSOLE_LOCK_INIT();
|
||||
|
||||
AJU_CONSOLE_LOCK();
|
||||
v = aju_cons_control_read();
|
||||
v &= ~ALTERA_JTAG_UART_CONTROL_AC;
|
||||
aju_cons_control_write(v);
|
||||
AJU_CONSOLE_UNLOCK();
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cnterm(struct consdev *cp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
aju_cngetc(struct consdev *cp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
AJU_CONSOLE_LOCK();
|
||||
ret = aju_cons_read();
|
||||
AJU_CONSOLE_UNLOCK();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cnputc(struct consdev *cp, int c)
|
||||
{
|
||||
|
||||
AJU_CONSOLE_LOCK();
|
||||
aju_cons_write(c);
|
||||
AJU_CONSOLE_UNLOCK();
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cngrab(struct consdev *cp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
aju_cnungrab(struct consdev *cp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CONSOLE_DRIVER(aju);
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
/*
|
||||
* FDT bus attachment for Altera JTAG UARTs.
|
||||
*/
|
||||
static int
|
||||
altera_jtag_uart_fdt_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "altera,jtag_uart-11_0")) {
|
||||
device_set_desc(dev, "Altera JTAG UART");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_jtag_uart_fdt_attach(device_t dev)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
sc = device_get_softc(dev);
|
||||
sc->ajus_dev = dev;
|
||||
sc->ajus_unit = device_get_unit(dev);
|
||||
sc->ajus_mem_rid = 0;
|
||||
sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->ajus_mem_rid, RF_ACTIVE);
|
||||
if (sc->ajus_mem_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt support is optional -- if we can't allocate an IRQ, then
|
||||
* we fall back on polling.
|
||||
*/
|
||||
sc->ajus_irq_rid = 0;
|
||||
sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||
&sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
|
||||
if (sc->ajus_irq_res == NULL)
|
||||
device_printf(dev,
|
||||
"IRQ unavailable; selecting polled operation\n");
|
||||
error = altera_jtag_uart_attach(sc);
|
||||
out:
|
||||
if (error) {
|
||||
if (sc->ajus_irq_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->ajus_irq_rid, sc->ajus_irq_res);
|
||||
if (sc->ajus_mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
sc->ajus_mem_rid, sc->ajus_mem_res);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_jtag_uart_fdt_detach(device_t dev)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
|
||||
__func__));
|
||||
|
||||
altera_jtag_uart_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
|
||||
sc->ajus_irq_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
|
||||
sc->ajus_mem_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_jtag_uart_fdt_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_jtag_uart_fdt_probe),
|
||||
DEVMETHOD(device_attach, altera_jtag_uart_fdt_attach),
|
||||
DEVMETHOD(device_detach, altera_jtag_uart_fdt_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_jtag_uart_fdt_driver = {
|
||||
"altera_jtag_uart",
|
||||
altera_jtag_uart_fdt_methods,
|
||||
sizeof(struct altera_jtag_uart_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(altera_jtag_uart, simplebus, altera_jtag_uart_fdt_driver, 0, 0);
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
|
||||
|
||||
/*
|
||||
* Nexus bus attachment for Altera JTAG UARTs. Appropriate for most Altera
|
||||
* FPGA SoC-style configurations in which the IP core will be exposed to the
|
||||
* processor via a memory-mapped Avalon bus.
|
||||
*/
|
||||
static int
|
||||
altera_jtag_uart_nexus_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "Altera JTAG UART");
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_jtag_uart_nexus_attach(device_t dev)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
sc = device_get_softc(dev);
|
||||
sc->ajus_dev = dev;
|
||||
sc->ajus_unit = device_get_unit(dev);
|
||||
sc->ajus_mem_rid = 0;
|
||||
sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->ajus_mem_rid, RF_ACTIVE);
|
||||
if (sc->ajus_mem_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt support is optional -- if we can't allocate an IRQ, then
|
||||
* we fall back on polling.
|
||||
*/
|
||||
sc->ajus_irq_rid = 0;
|
||||
sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||
&sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
|
||||
if (sc->ajus_irq_res == NULL)
|
||||
device_printf(dev,
|
||||
"IRQ unavailable; selecting polled operation\n");
|
||||
error = altera_jtag_uart_attach(sc);
|
||||
out:
|
||||
if (error) {
|
||||
if (sc->ajus_irq_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->ajus_irq_rid, sc->ajus_irq_res);
|
||||
if (sc->ajus_mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
sc->ajus_mem_rid, sc->ajus_mem_res);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_jtag_uart_nexus_detach(device_t dev)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
|
||||
__func__));
|
||||
|
||||
altera_jtag_uart_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
|
||||
sc->ajus_irq_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
|
||||
sc->ajus_mem_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_jtag_uart_nexus_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_jtag_uart_nexus_probe),
|
||||
DEVMETHOD(device_attach, altera_jtag_uart_nexus_attach),
|
||||
DEVMETHOD(device_detach, altera_jtag_uart_nexus_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_jtag_uart_nexus_driver = {
|
||||
"altera_jtag_uart",
|
||||
altera_jtag_uart_nexus_methods,
|
||||
sizeof(struct altera_jtag_uart_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(altera_jtag_uart, nexus, altera_jtag_uart_nexus_driver, 0, 0);
|
||||
|
|
@ -1,561 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2011-2012, 2016 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/tty.h>
|
||||
|
||||
#include <ddb/ddb.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
|
||||
|
||||
/*
|
||||
* If one of the Altera JTAG UARTs is currently the system console, register
|
||||
* it here.
|
||||
*/
|
||||
static struct altera_jtag_uart_softc *aju_cons_sc;
|
||||
|
||||
static tsw_outwakeup_t aju_outwakeup;
|
||||
static void aju_ac_callout(void *);
|
||||
static void aju_io_callout(void *);
|
||||
|
||||
static struct ttydevsw aju_ttydevsw = {
|
||||
.tsw_flags = TF_NOPREFIX,
|
||||
.tsw_outwakeup = aju_outwakeup,
|
||||
};
|
||||
|
||||
/*
|
||||
* When polling for the AC bit, the number of times we have to not see it
|
||||
* before assuming JTAG has disappeared on us. By default, four seconds.
|
||||
*/
|
||||
#define AJU_JTAG_MAXMISS 20
|
||||
|
||||
/*
|
||||
* Polling intervals for input/output and JTAG connection events.
|
||||
*/
|
||||
#define AJU_IO_POLLINTERVAL (hz/100)
|
||||
#define AJU_AC_POLLINTERVAL (hz/5)
|
||||
|
||||
/*
|
||||
* Statistics on JTAG removal events when sending, for debugging purposes
|
||||
* only.
|
||||
*/
|
||||
static u_int aju_jtag_vanished;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_vanished, CTLFLAG_RW,
|
||||
&aju_jtag_vanished, 0, "Number of times JTAG has vanished");
|
||||
|
||||
static u_int aju_jtag_appeared;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_appeared, CTLFLAG_RW,
|
||||
&aju_jtag_appeared, 0, "Number of times JTAG has appeared");
|
||||
|
||||
SYSCTL_INT(_debug, OID_AUTO, aju_cons_jtag_present, CTLFLAG_RW,
|
||||
&aju_cons_jtag_present, 0, "JTAG console present flag");
|
||||
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_cons_jtag_missed, CTLFLAG_RW,
|
||||
&aju_cons_jtag_missed, 0, "JTAG console missed counter");
|
||||
|
||||
/*
|
||||
* Interrupt-related statistics.
|
||||
*/
|
||||
static u_int aju_intr_readable_enabled;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_readable_enabled, CTLFLAG_RW,
|
||||
&aju_intr_readable_enabled, 0, "Number of times read interrupt enabled");
|
||||
|
||||
static u_int aju_intr_writable_disabled;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_disabled, CTLFLAG_RW,
|
||||
&aju_intr_writable_disabled, 0,
|
||||
"Number of times write interrupt disabled");
|
||||
|
||||
static u_int aju_intr_writable_enabled;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_enabled, CTLFLAG_RW,
|
||||
&aju_intr_writable_enabled, 0,
|
||||
"Number of times write interrupt enabled");
|
||||
|
||||
static u_int aju_intr_disabled;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_disabled, CTLFLAG_RW,
|
||||
&aju_intr_disabled, 0, "Number of times write interrupt disabled");
|
||||
|
||||
static u_int aju_intr_read_count;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_read_count, CTLFLAG_RW,
|
||||
&aju_intr_read_count, 0, "Number of times read interrupt fired");
|
||||
|
||||
static u_int aju_intr_write_count;
|
||||
SYSCTL_UINT(_debug, OID_AUTO, aju_intr_write_count, CTLFLAG_RW,
|
||||
&aju_intr_write_count, 0, "Number of times write interrupt fired");
|
||||
|
||||
/*
|
||||
* Low-level read and write register routines; the Altera UART is little
|
||||
* endian, so we byte swap 32-bit reads and writes.
|
||||
*/
|
||||
static inline uint32_t
|
||||
aju_data_read(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
|
||||
return (le32toh(bus_read_4(sc->ajus_mem_res,
|
||||
ALTERA_JTAG_UART_DATA_OFF)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
aju_data_write(struct altera_jtag_uart_softc *sc, uint32_t v)
|
||||
{
|
||||
|
||||
bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_DATA_OFF, htole32(v));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
aju_control_read(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
|
||||
return (le32toh(bus_read_4(sc->ajus_mem_res,
|
||||
ALTERA_JTAG_UART_CONTROL_OFF)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
aju_control_write(struct altera_jtag_uart_softc *sc, uint32_t v)
|
||||
{
|
||||
|
||||
bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_CONTROL_OFF,
|
||||
htole32(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Slightly higher-level routines aware of buffering and flow control.
|
||||
*/
|
||||
static inline int
|
||||
aju_writable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
|
||||
return ((aju_control_read(sc) &
|
||||
ALTERA_JTAG_UART_CONTROL_WSPACE) != 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
aju_readable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
if (*sc->ajus_buffer_validp)
|
||||
return (1);
|
||||
v = aju_data_read(sc);
|
||||
if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
|
||||
*sc->ajus_buffer_validp = 1;
|
||||
*sc->ajus_buffer_datap = (v & ALTERA_JTAG_UART_DATA_DATA);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char
|
||||
aju_read(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
while (!aju_readable(sc));
|
||||
*sc->ajus_buffer_validp = 0;
|
||||
return (*sc->ajus_buffer_datap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines for enabling and disabling interrupts for read and write.
|
||||
*/
|
||||
static void
|
||||
aju_intr_readable_enable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
atomic_add_int(&aju_intr_readable_enabled, 1);
|
||||
v = aju_control_read(sc);
|
||||
v |= ALTERA_JTAG_UART_CONTROL_RE;
|
||||
aju_control_write(sc, v);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_intr_writable_enable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
atomic_add_int(&aju_intr_writable_enabled, 1);
|
||||
v = aju_control_read(sc);
|
||||
v |= ALTERA_JTAG_UART_CONTROL_WE;
|
||||
aju_control_write(sc, v);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_intr_writable_disable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
atomic_add_int(&aju_intr_writable_disabled, 1);
|
||||
v = aju_control_read(sc);
|
||||
v &= ~ALTERA_JTAG_UART_CONTROL_WE;
|
||||
aju_control_write(sc, v);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_intr_disable(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
atomic_add_int(&aju_intr_disabled, 1);
|
||||
v = aju_control_read(sc);
|
||||
v &= ~(ALTERA_JTAG_UART_CONTROL_RE | ALTERA_JTAG_UART_CONTROL_WE);
|
||||
aju_control_write(sc, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* The actual work of checking for, and handling, available reads. This is
|
||||
* used in both polled and interrupt-driven modes, as JTAG UARTs may be hooked
|
||||
* up with, or without, IRQs allocated.
|
||||
*/
|
||||
static void
|
||||
aju_handle_input(struct altera_jtag_uart_softc *sc, struct tty *tp)
|
||||
{
|
||||
int c;
|
||||
|
||||
tty_assert_locked(tp);
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
while (aju_readable(sc)) {
|
||||
c = aju_read(sc);
|
||||
AJU_UNLOCK(sc);
|
||||
#ifdef KDB
|
||||
if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
|
||||
kdb_alt_break(c, &sc->ajus_alt_break_state);
|
||||
#endif
|
||||
ttydisc_rint(tp, c, 0);
|
||||
AJU_LOCK(sc);
|
||||
}
|
||||
AJU_UNLOCK(sc);
|
||||
ttydisc_rint_done(tp);
|
||||
AJU_LOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send output to the UART until either there's none left to send, or we run
|
||||
* out of room and need to await an interrupt so that we can start sending
|
||||
* again.
|
||||
*
|
||||
* XXXRW: It would be nice to query WSPACE at the beginning and write to the
|
||||
* FIFO in bugger chunks.
|
||||
*/
|
||||
static void
|
||||
aju_handle_output(struct altera_jtag_uart_softc *sc, struct tty *tp)
|
||||
{
|
||||
uint32_t v;
|
||||
uint8_t ch;
|
||||
|
||||
tty_assert_locked(tp);
|
||||
AJU_LOCK_ASSERT(sc);
|
||||
|
||||
AJU_UNLOCK(sc);
|
||||
while (ttydisc_getc_poll(tp) != 0) {
|
||||
AJU_LOCK(sc);
|
||||
if (*sc->ajus_jtag_presentp == 0) {
|
||||
/*
|
||||
* If JTAG is not present, then we will drop this
|
||||
* character instead of perhaps scheduling an
|
||||
* interrupt to let us know when there is buffer
|
||||
* space. Otherwise we might get a write interrupt
|
||||
* later even though we aren't interested in sending
|
||||
* anymore. Loop to drain TTY-layer buffer.
|
||||
*/
|
||||
AJU_UNLOCK(sc);
|
||||
if (ttydisc_getc(tp, &ch, sizeof(ch)) !=
|
||||
sizeof(ch))
|
||||
panic("%s: ttydisc_getc", __func__);
|
||||
continue;
|
||||
}
|
||||
v = aju_control_read(sc);
|
||||
if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) == 0) {
|
||||
if (sc->ajus_irq_res != NULL &&
|
||||
(v & ALTERA_JTAG_UART_CONTROL_WE) == 0)
|
||||
aju_intr_writable_enable(sc);
|
||||
return;
|
||||
}
|
||||
AJU_UNLOCK(sc);
|
||||
if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch))
|
||||
panic("%s: ttydisc_getc 2", __func__);
|
||||
AJU_LOCK(sc);
|
||||
|
||||
/*
|
||||
* XXXRW: There is a slight race here in which we test for
|
||||
* writability, drop the lock, get the character from the tty
|
||||
* layer, re-acquire the lock, and then write. It's possible
|
||||
* for other code -- specifically, the low-level console -- to
|
||||
* have* written in the mean time, which might mean that there
|
||||
* is no longer space. The BERI memory bus will cause this
|
||||
* write to block, wedging the processor until space is
|
||||
* available -- which could be a while if JTAG is not
|
||||
* attached!
|
||||
*
|
||||
* The 'easy' fix is to drop the character if WSPACE has
|
||||
* become unset. Not sure what the 'hard' fix is.
|
||||
*/
|
||||
aju_data_write(sc, ch);
|
||||
AJU_UNLOCK(sc);
|
||||
}
|
||||
AJU_LOCK(sc);
|
||||
|
||||
/*
|
||||
* If interrupts are configured, and there's no data to write, but we
|
||||
* had previously enabled write interrupts, disable them now.
|
||||
*/
|
||||
v = aju_control_read(sc);
|
||||
if (sc->ajus_irq_res != NULL && (v & ALTERA_JTAG_UART_CONTROL_WE) != 0)
|
||||
aju_intr_writable_disable(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_outwakeup(struct tty *tp)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc = tty_softc(tp);
|
||||
|
||||
tty_assert_locked(tp);
|
||||
|
||||
AJU_LOCK(sc);
|
||||
aju_handle_output(sc, tp);
|
||||
AJU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_io_callout(void *arg)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc = arg;
|
||||
struct tty *tp = sc->ajus_ttyp;
|
||||
|
||||
tty_lock(tp);
|
||||
AJU_LOCK(sc);
|
||||
|
||||
/*
|
||||
* It would be convenient if we could share code with aju_intr() here
|
||||
* by testing the control register for ALTERA_JTAG_UART_CONTROL_RI and
|
||||
* ALTERA_JTAG_UART_CONTROL_WI. Unfortunately, it's not clear that
|
||||
* this is supported, so do all the work to poll for both input and
|
||||
* output.
|
||||
*/
|
||||
aju_handle_input(sc, tp);
|
||||
aju_handle_output(sc, tp);
|
||||
|
||||
/*
|
||||
* Reschedule next poll attempt. There's some argument that we should
|
||||
* do adaptive polling based on the expectation of I/O: is something
|
||||
* pending in the output buffer, or have we recently had input, but we
|
||||
* don't.
|
||||
*/
|
||||
callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
|
||||
aju_io_callout, sc);
|
||||
AJU_UNLOCK(sc);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_ac_callout(void *arg)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc = arg;
|
||||
struct tty *tp = sc->ajus_ttyp;
|
||||
uint32_t v;
|
||||
|
||||
tty_lock(tp);
|
||||
AJU_LOCK(sc);
|
||||
v = aju_control_read(sc);
|
||||
if (v & ALTERA_JTAG_UART_CONTROL_AC) {
|
||||
v &= ~ALTERA_JTAG_UART_CONTROL_AC;
|
||||
aju_control_write(sc, v);
|
||||
if (*sc->ajus_jtag_presentp == 0) {
|
||||
*sc->ajus_jtag_presentp = 1;
|
||||
atomic_add_int(&aju_jtag_appeared, 1);
|
||||
aju_handle_output(sc, tp);
|
||||
}
|
||||
|
||||
/* Any hit eliminates all recent misses. */
|
||||
*sc->ajus_jtag_missedp = 0;
|
||||
} else if (*sc->ajus_jtag_presentp != 0) {
|
||||
/*
|
||||
* If we've exceeded our tolerance for misses, mark JTAG as
|
||||
* disconnected and drain output. Otherwise, bump the miss
|
||||
* counter.
|
||||
*/
|
||||
if (*sc->ajus_jtag_missedp > AJU_JTAG_MAXMISS) {
|
||||
*sc->ajus_jtag_presentp = 0;
|
||||
atomic_add_int(&aju_jtag_vanished, 1);
|
||||
aju_handle_output(sc, tp);
|
||||
} else
|
||||
(*sc->ajus_jtag_missedp)++;
|
||||
}
|
||||
callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
|
||||
aju_ac_callout, sc);
|
||||
AJU_UNLOCK(sc);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
aju_intr(void *arg)
|
||||
{
|
||||
struct altera_jtag_uart_softc *sc = arg;
|
||||
struct tty *tp = sc->ajus_ttyp;
|
||||
uint32_t v;
|
||||
|
||||
tty_lock(tp);
|
||||
AJU_LOCK(sc);
|
||||
v = aju_control_read(sc);
|
||||
if (v & ALTERA_JTAG_UART_CONTROL_RI) {
|
||||
atomic_add_int(&aju_intr_read_count, 1);
|
||||
aju_handle_input(sc, tp);
|
||||
}
|
||||
if (v & ALTERA_JTAG_UART_CONTROL_WI) {
|
||||
atomic_add_int(&aju_intr_write_count, 1);
|
||||
aju_handle_output(sc, tp);
|
||||
}
|
||||
AJU_UNLOCK(sc);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
int
|
||||
altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
struct tty *tp;
|
||||
int error;
|
||||
|
||||
AJU_LOCK_INIT(sc);
|
||||
|
||||
/*
|
||||
* XXXRW: Currently, we detect the console solely based on it using a
|
||||
* reserved address, and borrow console-level locks and buffer if so.
|
||||
* Is there a better way?
|
||||
*/
|
||||
if (rman_get_start(sc->ajus_mem_res) == BERI_UART_BASE) {
|
||||
sc->ajus_lockp = &aju_cons_lock;
|
||||
sc->ajus_buffer_validp = &aju_cons_buffer_valid;
|
||||
sc->ajus_buffer_datap = &aju_cons_buffer_data;
|
||||
sc->ajus_jtag_presentp = &aju_cons_jtag_present;
|
||||
sc->ajus_jtag_missedp = &aju_cons_jtag_missed;
|
||||
sc->ajus_flags |= ALTERA_JTAG_UART_FLAG_CONSOLE;
|
||||
} else {
|
||||
sc->ajus_lockp = &sc->ajus_lock;
|
||||
sc->ajus_buffer_validp = &sc->ajus_buffer_valid;
|
||||
sc->ajus_buffer_datap = &sc->ajus_buffer_data;
|
||||
sc->ajus_jtag_presentp = &sc->ajus_jtag_present;
|
||||
sc->ajus_jtag_missedp = &sc->ajus_jtag_missed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable interrupts regardless of whether or not we plan to use
|
||||
* them. We will register an interrupt handler now if they will be
|
||||
* used, but not re-enable intil later once the remainder of the tty
|
||||
* layer is properly initialised, as we're not ready for input yet.
|
||||
*/
|
||||
AJU_LOCK(sc);
|
||||
aju_intr_disable(sc);
|
||||
AJU_UNLOCK(sc);
|
||||
if (sc->ajus_irq_res != NULL) {
|
||||
error = bus_setup_intr(sc->ajus_dev, sc->ajus_irq_res,
|
||||
INTR_ENTROPY | INTR_TYPE_TTY | INTR_MPSAFE, NULL,
|
||||
aju_intr, sc, &sc->ajus_irq_cookie);
|
||||
if (error) {
|
||||
device_printf(sc->ajus_dev,
|
||||
"could not activate interrupt\n");
|
||||
AJU_LOCK_DESTROY(sc);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
tp = sc->ajus_ttyp = tty_alloc(&aju_ttydevsw, sc);
|
||||
if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE) {
|
||||
aju_cons_sc = sc;
|
||||
tty_init_console(tp, 0);
|
||||
}
|
||||
tty_makedev(tp, NULL, "%s%d", AJU_TTYNAME, sc->ajus_unit);
|
||||
|
||||
/*
|
||||
* If we will be using interrupts, enable them now; otherwise, start
|
||||
* polling. From this point onwards, input can arrive.
|
||||
*/
|
||||
if (sc->ajus_irq_res != NULL) {
|
||||
AJU_LOCK(sc);
|
||||
aju_intr_readable_enable(sc);
|
||||
AJU_UNLOCK(sc);
|
||||
} else {
|
||||
callout_init(&sc->ajus_io_callout, 1);
|
||||
callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
|
||||
aju_io_callout, sc);
|
||||
}
|
||||
callout_init(&sc->ajus_ac_callout, 1);
|
||||
callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
|
||||
aju_ac_callout, sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc)
|
||||
{
|
||||
struct tty *tp = sc->ajus_ttyp;
|
||||
|
||||
/*
|
||||
* If we're using interrupts, disable and release the interrupt
|
||||
* handler now. Otherwise drain the polling timeout.
|
||||
*/
|
||||
if (sc->ajus_irq_res != NULL) {
|
||||
AJU_LOCK(sc);
|
||||
aju_intr_disable(sc);
|
||||
AJU_UNLOCK(sc);
|
||||
bus_teardown_intr(sc->ajus_dev, sc->ajus_irq_res,
|
||||
sc->ajus_irq_cookie);
|
||||
} else
|
||||
callout_drain(&sc->ajus_io_callout);
|
||||
callout_drain(&sc->ajus_ac_callout);
|
||||
if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
|
||||
aju_cons_sc = NULL;
|
||||
tty_lock(tp);
|
||||
tty_rel_gone(tp);
|
||||
AJU_LOCK_DESTROY(sc);
|
||||
}
|
||||
|
|
@ -1,637 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Altera mSGDMA driver. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_platform.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/sglist.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cache.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#endif
|
||||
|
||||
#include <dev/xdma/xdma.h>
|
||||
#include "xdma_if.h"
|
||||
#include "opt_altera_msgdma.h"
|
||||
|
||||
#include <dev/altera/msgdma/msgdma.h>
|
||||
|
||||
#define MSGDMA_DEBUG
|
||||
#undef MSGDMA_DEBUG
|
||||
|
||||
#ifdef MSGDMA_DEBUG
|
||||
#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define MSGDMA_NCHANNELS 1
|
||||
|
||||
struct msgdma_channel {
|
||||
struct msgdma_softc *sc;
|
||||
struct mtx mtx;
|
||||
xdma_channel_t *xchan;
|
||||
struct proc *p;
|
||||
int used;
|
||||
int index;
|
||||
int idx_head;
|
||||
int idx_tail;
|
||||
|
||||
struct msgdma_desc **descs;
|
||||
bus_dma_segment_t *descs_phys;
|
||||
uint32_t descs_num;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t *dma_map;
|
||||
uint32_t map_descr;
|
||||
uint8_t map_err;
|
||||
uint32_t descs_used_count;
|
||||
};
|
||||
|
||||
struct msgdma_softc {
|
||||
device_t dev;
|
||||
struct resource *res[3];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_space_tag_t bst_d;
|
||||
bus_space_handle_t bsh_d;
|
||||
void *ih;
|
||||
struct msgdma_desc desc;
|
||||
struct msgdma_channel channels[MSGDMA_NCHANNELS];
|
||||
};
|
||||
|
||||
static struct resource_spec msgdma_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
#define HWTYPE_NONE 0
|
||||
#define HWTYPE_STD 1
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{ "altr,msgdma-16.0", HWTYPE_STD },
|
||||
{ "altr,msgdma-1.0", HWTYPE_STD },
|
||||
{ NULL, HWTYPE_NONE },
|
||||
};
|
||||
|
||||
static int msgdma_probe(device_t dev);
|
||||
static int msgdma_attach(device_t dev);
|
||||
static int msgdma_detach(device_t dev);
|
||||
|
||||
static inline uint32_t
|
||||
msgdma_next_desc(struct msgdma_channel *chan, uint32_t curidx)
|
||||
{
|
||||
|
||||
return ((curidx + 1) % chan->descs_num);
|
||||
}
|
||||
|
||||
static void
|
||||
msgdma_intr(void *arg)
|
||||
{
|
||||
xdma_transfer_status_t status;
|
||||
struct xdma_transfer_status st;
|
||||
struct msgdma_desc *desc;
|
||||
struct msgdma_channel *chan;
|
||||
struct xdma_channel *xchan;
|
||||
struct msgdma_softc *sc;
|
||||
uint32_t tot_copied;
|
||||
|
||||
sc = arg;
|
||||
chan = &sc->channels[0];
|
||||
xchan = chan->xchan;
|
||||
|
||||
dprintf("%s(%d): status 0x%08x next_descr 0x%08x, control 0x%08x\n",
|
||||
__func__, device_get_unit(sc->dev),
|
||||
READ4_DESC(sc, PF_STATUS),
|
||||
READ4_DESC(sc, PF_NEXT_LO),
|
||||
READ4_DESC(sc, PF_CONTROL));
|
||||
|
||||
tot_copied = 0;
|
||||
|
||||
while (chan->idx_tail != chan->idx_head) {
|
||||
dprintf("%s: idx_tail %d idx_head %d\n", __func__,
|
||||
chan->idx_tail, chan->idx_head);
|
||||
bus_dmamap_sync(chan->dma_tag, chan->dma_map[chan->idx_tail],
|
||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
||||
|
||||
desc = chan->descs[chan->idx_tail];
|
||||
if ((le32toh(desc->control) & CONTROL_OWN) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
tot_copied += le32toh(desc->transferred);
|
||||
st.error = 0;
|
||||
st.transferred = le32toh(desc->transferred);
|
||||
xchan_seg_done(xchan, &st);
|
||||
|
||||
chan->idx_tail = msgdma_next_desc(chan, chan->idx_tail);
|
||||
atomic_subtract_int(&chan->descs_used_count, 1);
|
||||
}
|
||||
|
||||
WRITE4_DESC(sc, PF_STATUS, PF_STATUS_IRQ);
|
||||
|
||||
/* Finish operation */
|
||||
status.error = 0;
|
||||
status.transferred = tot_copied;
|
||||
xdma_callback(chan->xchan, &status);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_reset(struct msgdma_softc *sc)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
dprintf("%s: read status: %x\n", __func__, READ4(sc, 0x00));
|
||||
dprintf("%s: read control: %x\n", __func__, READ4(sc, 0x04));
|
||||
dprintf("%s: read 1: %x\n", __func__, READ4(sc, 0x08));
|
||||
dprintf("%s: read 2: %x\n", __func__, READ4(sc, 0x0C));
|
||||
|
||||
WRITE4(sc, DMA_CONTROL, CONTROL_RESET);
|
||||
|
||||
timeout = 100;
|
||||
do {
|
||||
if ((READ4(sc, DMA_STATUS) & STATUS_RESETTING) == 0)
|
||||
break;
|
||||
} while (timeout--);
|
||||
|
||||
dprintf("timeout %d\n", timeout);
|
||||
|
||||
if (timeout == 0)
|
||||
return (-1);
|
||||
|
||||
dprintf("%s: read control after reset: %x\n",
|
||||
__func__, READ4(sc, DMA_CONTROL));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_probe(device_t dev)
|
||||
{
|
||||
int hwtype;
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
|
||||
if (hwtype == HWTYPE_NONE)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Altera mSGDMA");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_attach(device_t dev)
|
||||
{
|
||||
struct msgdma_softc *sc;
|
||||
phandle_t xref, node;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, msgdma_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources for device\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* CSR memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
/* Descriptor memory interface */
|
||||
sc->bst_d = rman_get_bustag(sc->res[1]);
|
||||
sc->bsh_d = rman_get_bushandle(sc->res[1]);
|
||||
|
||||
/* Setup interrupt handler */
|
||||
err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, msgdma_intr, sc, &sc->ih);
|
||||
if (err) {
|
||||
device_printf(dev, "Unable to alloc interrupt resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
xref = OF_xref_from_node(node);
|
||||
OF_device_register_xref(xref, dev);
|
||||
|
||||
if (msgdma_reset(sc) != 0)
|
||||
return (-1);
|
||||
|
||||
WRITE4(sc, DMA_CONTROL, CONTROL_GIEM);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_detach(device_t dev)
|
||||
{
|
||||
struct msgdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
msgdma_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
|
||||
chan = (struct msgdma_channel *)arg;
|
||||
KASSERT(chan != NULL, ("xchan is NULL"));
|
||||
|
||||
if (err) {
|
||||
chan->map_err = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
chan->descs_phys[chan->map_descr].ds_addr = segs[0].ds_addr;
|
||||
chan->descs_phys[chan->map_descr].ds_len = segs[0].ds_len;
|
||||
|
||||
dprintf("map desc %d: descs phys %lx len %ld\n",
|
||||
chan->map_descr, segs[0].ds_addr, segs[0].ds_len);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_desc_free(struct msgdma_softc *sc, struct msgdma_channel *chan)
|
||||
{
|
||||
struct msgdma_desc *desc;
|
||||
int nsegments;
|
||||
int i;
|
||||
|
||||
nsegments = chan->descs_num;
|
||||
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
desc = chan->descs[i];
|
||||
bus_dmamap_unload(chan->dma_tag, chan->dma_map[i]);
|
||||
bus_dmamem_free(chan->dma_tag, desc, chan->dma_map[i]);
|
||||
}
|
||||
|
||||
bus_dma_tag_destroy(chan->dma_tag);
|
||||
free(chan->descs, M_DEVBUF);
|
||||
free(chan->dma_map, M_DEVBUF);
|
||||
free(chan->descs_phys, M_DEVBUF);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_desc_alloc(struct msgdma_softc *sc, struct msgdma_channel *chan,
|
||||
uint32_t desc_size, uint32_t align)
|
||||
{
|
||||
int nsegments;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
nsegments = chan->descs_num;
|
||||
|
||||
dprintf("%s: nseg %d\n", __func__, nsegments);
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
bus_get_dma_tag(sc->dev),
|
||||
align, 0, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
desc_size, 1, /* maxsize, nsegments*/
|
||||
desc_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&chan->dma_tag);
|
||||
if (err) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't create bus_dma tag.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Descriptors. */
|
||||
chan->descs = malloc(nsegments * sizeof(struct msgdma_desc *),
|
||||
M_DEVBUF, (M_WAITOK | M_ZERO));
|
||||
chan->dma_map = malloc(nsegments * sizeof(bus_dmamap_t),
|
||||
M_DEVBUF, (M_WAITOK | M_ZERO));
|
||||
chan->descs_phys = malloc(nsegments * sizeof(bus_dma_segment_t),
|
||||
M_DEVBUF, (M_WAITOK | M_ZERO));
|
||||
|
||||
/* Allocate bus_dma memory for each descriptor. */
|
||||
for (i = 0; i < nsegments; i++) {
|
||||
err = bus_dmamem_alloc(chan->dma_tag, (void **)&chan->descs[i],
|
||||
BUS_DMA_WAITOK | BUS_DMA_ZERO, &chan->dma_map[i]);
|
||||
if (err) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't allocate memory for descriptors.\n",
|
||||
__func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
chan->map_err = 0;
|
||||
chan->map_descr = i;
|
||||
err = bus_dmamap_load(chan->dma_tag, chan->dma_map[i], chan->descs[i],
|
||||
desc_size, msgdma_dmamap_cb, chan, BUS_DMA_WAITOK);
|
||||
if (err) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't load DMA map.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (chan->map_err != 0) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't load DMA map.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_alloc(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
struct msgdma_softc *sc;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
for (i = 0; i < MSGDMA_NCHANNELS; i++) {
|
||||
chan = &sc->channels[i];
|
||||
if (chan->used == 0) {
|
||||
chan->xchan = xchan;
|
||||
xchan->chan = (void *)chan;
|
||||
if ((xchan->caps & XCHAN_CAP_IOMMU) == 0)
|
||||
xchan->caps |= XCHAN_CAP_BUSDMA;
|
||||
chan->index = i;
|
||||
chan->sc = sc;
|
||||
chan->used = 1;
|
||||
chan->idx_head = 0;
|
||||
chan->idx_tail = 0;
|
||||
chan->descs_used_count = 0;
|
||||
chan->descs_num = 1024;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_free(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
struct msgdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct msgdma_channel *)xchan->chan;
|
||||
|
||||
msgdma_desc_free(sc, chan);
|
||||
|
||||
chan->used = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_capacity(device_t dev, xdma_channel_t *xchan,
|
||||
uint32_t *capacity)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
uint32_t c;
|
||||
|
||||
chan = (struct msgdma_channel *)xchan->chan;
|
||||
|
||||
/* At least one descriptor must be left empty. */
|
||||
c = (chan->descs_num - chan->descs_used_count - 1);
|
||||
|
||||
*capacity = c;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
|
||||
struct xdma_sglist *sg, uint32_t sg_n)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
struct msgdma_desc *desc;
|
||||
struct msgdma_softc *sc;
|
||||
bus_addr_t src_addr_lo;
|
||||
bus_addr_t dst_addr_lo;
|
||||
uint32_t len;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct msgdma_channel *)xchan->chan;
|
||||
|
||||
for (i = 0; i < sg_n; i++) {
|
||||
src_addr_lo = sg[i].src_addr;
|
||||
dst_addr_lo = sg[i].dst_addr;
|
||||
len = (uint32_t)sg[i].len;
|
||||
|
||||
dprintf("%s: src %x dst %x len %d\n", __func__,
|
||||
src_addr_lo, dst_addr_lo, len);
|
||||
|
||||
desc = chan->descs[chan->idx_head];
|
||||
#if defined(ALTERA_MSGDMA_DESC_EXT) || defined(ALTERA_MSGDMA_DESC_PF_EXT)
|
||||
desc->read_hi = htole32(src_addr_lo >> 32);
|
||||
desc->write_hi = htole32(dst_addr_lo >> 32);
|
||||
#endif
|
||||
desc->read_lo = htole32(src_addr_lo);
|
||||
desc->write_lo = htole32(dst_addr_lo);
|
||||
desc->length = htole32(len);
|
||||
desc->transferred = 0;
|
||||
desc->status = 0;
|
||||
desc->reserved = 0;
|
||||
desc->control = 0;
|
||||
|
||||
if (sg[i].direction == XDMA_MEM_TO_DEV) {
|
||||
if (sg[i].first == 1) {
|
||||
desc->control |= htole32(CONTROL_GEN_SOP);
|
||||
}
|
||||
|
||||
if (sg[i].last == 1) {
|
||||
desc->control |= htole32(CONTROL_GEN_EOP);
|
||||
desc->control |= htole32(CONTROL_TC_IRQ_EN |
|
||||
CONTROL_ET_IRQ_EN | CONTROL_ERR_M);
|
||||
}
|
||||
} else {
|
||||
desc->control |= htole32(CONTROL_END_ON_EOP | (1 << 13));
|
||||
desc->control |= htole32(CONTROL_TC_IRQ_EN |
|
||||
CONTROL_ET_IRQ_EN | CONTROL_ERR_M);
|
||||
}
|
||||
|
||||
tmp = chan->idx_head;
|
||||
|
||||
atomic_add_int(&chan->descs_used_count, 1);
|
||||
chan->idx_head = msgdma_next_desc(chan, chan->idx_head);
|
||||
|
||||
desc->control |= htole32(CONTROL_OWN | CONTROL_GO);
|
||||
|
||||
bus_dmamap_sync(chan->dma_tag, chan->dma_map[tmp],
|
||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
struct msgdma_desc *desc;
|
||||
struct msgdma_softc *sc;
|
||||
uint32_t addr;
|
||||
uint32_t reg;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
dprintf("%s(%d)\n", __func__, device_get_unit(dev));
|
||||
|
||||
chan = (struct msgdma_channel *)xchan->chan;
|
||||
|
||||
ret = msgdma_desc_alloc(sc, chan, sizeof(struct msgdma_desc), 16);
|
||||
if (ret != 0) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't allocate descriptors.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < chan->descs_num; i++) {
|
||||
desc = chan->descs[i];
|
||||
|
||||
if (i == (chan->descs_num - 1)) {
|
||||
desc->next = htole32(chan->descs_phys[0].ds_addr);
|
||||
} else {
|
||||
desc->next = htole32(chan->descs_phys[i+1].ds_addr);
|
||||
}
|
||||
|
||||
dprintf("%s(%d): desc %d vaddr %lx next paddr %x\n", __func__,
|
||||
device_get_unit(dev), i, (uint64_t)desc, le32toh(desc->next));
|
||||
}
|
||||
|
||||
addr = chan->descs_phys[0].ds_addr;
|
||||
WRITE4_DESC(sc, PF_NEXT_LO, addr);
|
||||
WRITE4_DESC(sc, PF_NEXT_HI, 0);
|
||||
WRITE4_DESC(sc, PF_POLL_FREQ, 1000);
|
||||
|
||||
reg = (PF_CONTROL_GIEM | PF_CONTROL_DESC_POLL_EN);
|
||||
reg |= PF_CONTROL_RUN;
|
||||
WRITE4_DESC(sc, PF_CONTROL, reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
msgdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd)
|
||||
{
|
||||
struct msgdma_channel *chan;
|
||||
struct msgdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct msgdma_channel *)xchan->chan;
|
||||
|
||||
switch (cmd) {
|
||||
case XDMA_CMD_BEGIN:
|
||||
case XDMA_CMD_TERMINATE:
|
||||
case XDMA_CMD_PAUSE:
|
||||
/* TODO: implement me */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef FDT
|
||||
static int
|
||||
msgdma_ofw_md_data(device_t dev, pcell_t *cells, int ncells, void **ptr)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static device_method_t msgdma_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, msgdma_probe),
|
||||
DEVMETHOD(device_attach, msgdma_attach),
|
||||
DEVMETHOD(device_detach, msgdma_detach),
|
||||
|
||||
/* xDMA Interface */
|
||||
DEVMETHOD(xdma_channel_alloc, msgdma_channel_alloc),
|
||||
DEVMETHOD(xdma_channel_free, msgdma_channel_free),
|
||||
DEVMETHOD(xdma_channel_control, msgdma_channel_control),
|
||||
|
||||
/* xDMA SG Interface */
|
||||
DEVMETHOD(xdma_channel_capacity, msgdma_channel_capacity),
|
||||
DEVMETHOD(xdma_channel_prep_sg, msgdma_channel_prep_sg),
|
||||
DEVMETHOD(xdma_channel_submit_sg, msgdma_channel_submit_sg),
|
||||
|
||||
#ifdef FDT
|
||||
DEVMETHOD(xdma_ofw_md_data, msgdma_ofw_md_data),
|
||||
#endif
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t msgdma_driver = {
|
||||
"msgdma",
|
||||
msgdma_methods,
|
||||
sizeof(struct msgdma_softc),
|
||||
};
|
||||
|
||||
EARLY_DRIVER_MODULE(msgdma, simplebus, msgdma_driver, 0, 0,
|
||||
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_altera_msgdma.h"
|
||||
|
||||
/* Altera mSGDMA registers. */
|
||||
#define DMA_STATUS 0x00
|
||||
#define STATUS_RESETTING (1 << 6)
|
||||
#define DMA_CONTROL 0x04
|
||||
#define CONTROL_GIEM (1 << 4) /* Global Interrupt Enable Mask */
|
||||
#define CONTROL_RESET (1 << 1) /* Reset Dispatcher */
|
||||
|
||||
/* Descriptor fields. */
|
||||
#define CONTROL_GO (1 << 31) /* Commit all the descriptor info */
|
||||
#define CONTROL_OWN (1 << 30) /* Owned by hardware (prefetcher-enabled only) */
|
||||
#define CONTROL_EDE (1 << 24) /* Early done enable */
|
||||
#define CONTROL_ERR_S 16 /* Transmit Error, Error IRQ Enable */
|
||||
#define CONTROL_ERR_M (0xff << CONTROL_ERR_S)
|
||||
#define CONTROL_ET_IRQ_EN (1 << 15) /* Early Termination IRQ Enable */
|
||||
#define CONTROL_TC_IRQ_EN (1 << 14) /* Transfer Complete IRQ Enable */
|
||||
#define CONTROL_END_ON_EOP (1 << 12) /* End on EOP */
|
||||
#define CONTROL_PARK_WR (1 << 11) /* Park Writes */
|
||||
#define CONTROL_PARK_RD (1 << 10) /* Park Reads */
|
||||
#define CONTROL_GEN_EOP (1 << 9) /* Generate EOP */
|
||||
#define CONTROL_GEN_SOP (1 << 8) /* Generate SOP */
|
||||
#define CONTROL_TX_CHANNEL_S 0 /* Transmit Channel */
|
||||
#define CONTROL_TX_CHANNEL_M (0xff << CONTROL_TRANSMIT_CH_S)
|
||||
|
||||
/* Prefetcher */
|
||||
#define PF_CONTROL 0x00
|
||||
#define PF_CONTROL_GIEM (1 << 3)
|
||||
#define PF_CONTROL_RESET (1 << 2)
|
||||
#define PF_CONTROL_DESC_POLL_EN (1 << 1)
|
||||
#define PF_CONTROL_RUN (1 << 0)
|
||||
#define PF_NEXT_LO 0x04
|
||||
#define PF_NEXT_HI 0x08
|
||||
#define PF_POLL_FREQ 0x0C
|
||||
#define PF_STATUS 0x10
|
||||
#define PF_STATUS_IRQ (1 << 0)
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
le32toh(bus_space_read_4(_sc->bst, _sc->bsh, _reg))
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_space_write_4(_sc->bst, _sc->bsh, _reg, htole32(_val))
|
||||
|
||||
#define READ4_DESC(_sc, _reg) \
|
||||
le32toh(bus_space_read_4(_sc->bst_d, _sc->bsh_d, _reg))
|
||||
#define WRITE4_DESC(_sc, _reg, _val) \
|
||||
bus_space_write_4(_sc->bst_d, _sc->bsh_d, _reg, htole32(_val))
|
||||
|
||||
#if defined(ALTERA_MSGDMA_DESC_STD)
|
||||
|
||||
/* Standard descriptor format with prefetcher disabled. */
|
||||
struct msgdma_desc {
|
||||
uint32_t read_lo;
|
||||
uint32_t write_lo;
|
||||
uint32_t length;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
#elif defined(ALTERA_MSGDMA_DESC_EXT)
|
||||
|
||||
/* Extended descriptor format with prefetcher disabled. */
|
||||
struct msgdma_desc {
|
||||
uint32_t read_lo;
|
||||
uint32_t write_lo;
|
||||
uint32_t length;
|
||||
uint8_t write_burst;
|
||||
uint8_t read_burst;
|
||||
uint16_t seq_num;
|
||||
uint16_t write_stride;
|
||||
uint16_t read_stride;
|
||||
uint32_t read_hi;
|
||||
uint32_t write_hi;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
#elif defined(ALTERA_MSGDMA_DESC_PF_STD)
|
||||
|
||||
/* Standard descriptor format with prefetcher enabled. */
|
||||
struct msgdma_desc {
|
||||
uint32_t read_lo;
|
||||
uint32_t write_lo;
|
||||
uint32_t length;
|
||||
uint32_t next;
|
||||
uint32_t transferred;
|
||||
uint32_t status;
|
||||
uint32_t reserved;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
#elif defined(ALTERA_MSGDMA_DESC_PF_EXT)
|
||||
|
||||
/* Extended descriptor format with prefetcher enabled. */
|
||||
struct msgdma_desc {
|
||||
uint32_t read_lo;
|
||||
uint32_t write_lo;
|
||||
uint32_t length;
|
||||
uint32_t next;
|
||||
uint32_t transferred;
|
||||
uint32_t status;
|
||||
uint32_t reserved;
|
||||
uint8_t write_burst;
|
||||
uint8_t read_burst;
|
||||
uint16_t seq_num;
|
||||
uint16_t write_stride;
|
||||
uint16_t read_stride;
|
||||
uint32_t read_hi;
|
||||
uint32_t write_hi;
|
||||
uint32_t next_hi;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint32_t reserved3;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error "mSGDMA descriptor format (kernel option) is not set."
|
||||
|
||||
#endif
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Altera PIO (Parallel IO) device driver
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <dev/altera/pio/pio.h>
|
||||
#include "pio_if.h"
|
||||
|
||||
#define READ4(_sc, _reg) bus_read_4((_sc)->res[0], _reg)
|
||||
#define READ2(_sc, _reg) bus_read_2((_sc)->res[0], _reg)
|
||||
#define READ1(_sc, _reg) bus_read_1((_sc)->res[0], _reg)
|
||||
#define WRITE4(_sc, _reg, _val) bus_write_4((_sc)->res[0], _reg, _val)
|
||||
#define WRITE2(_sc, _reg, _val) bus_write_2((_sc)->res[0], _reg, _val)
|
||||
#define WRITE1(_sc, _reg, _val) bus_write_1((_sc)->res[0], _reg, _val)
|
||||
|
||||
struct pio_softc {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
void *ih;
|
||||
};
|
||||
|
||||
static struct resource_spec pio_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
pio_setup_irq(device_t dev, void *intr_handler, void *ih_user)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Setup interrupt handlers */
|
||||
if (bus_setup_intr(sc->dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, intr_handler, ih_user, &sc->ih)) {
|
||||
device_printf(sc->dev, "Unable to setup intr\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_teardown_irq(device_t dev)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
bus_teardown_intr(sc->dev, sc->res[1], sc->ih);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_read(device_t dev)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
return (READ4(sc, PIO_DATA));
|
||||
}
|
||||
|
||||
static int
|
||||
pio_set(device_t dev, int bit, int enable)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (enable)
|
||||
WRITE4(sc, PIO_OUTSET, bit);
|
||||
else
|
||||
WRITE4(sc, PIO_OUTCLR, bit);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_configure(device_t dev, int dir, int mask)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
WRITE4(sc, PIO_INT_MASK, mask);
|
||||
WRITE4(sc, PIO_DIR, dir);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,pio"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Altera PIO");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_attach(device_t dev)
|
||||
{
|
||||
struct pio_softc *sc;
|
||||
struct fdt_ic *fic;
|
||||
phandle_t node;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, pio_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
fic = malloc(sizeof(*fic), M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
fic->iph = node;
|
||||
fic->dev = dev;
|
||||
SLIST_INSERT_HEAD(&fdt_ic_list_head, fic, fdt_ics);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t pio_methods[] = {
|
||||
DEVMETHOD(device_probe, pio_probe),
|
||||
DEVMETHOD(device_attach, pio_attach),
|
||||
|
||||
/* pio_if.m */
|
||||
DEVMETHOD(pio_read, pio_read),
|
||||
DEVMETHOD(pio_configure, pio_configure),
|
||||
DEVMETHOD(pio_set, pio_set),
|
||||
DEVMETHOD(pio_setup_irq, pio_setup_irq),
|
||||
DEVMETHOD(pio_teardown_irq, pio_teardown_irq),
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t pio_driver = {
|
||||
"altera_pio",
|
||||
pio_methods,
|
||||
sizeof(struct pio_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(altera_pio, simplebus, pio_driver, 0, 0);
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define PIO_DATA 0x00
|
||||
#define PIO_DIR 0x04
|
||||
#define PIO_OUT(n) (1 << n)
|
||||
#define PIO_OUT_ALL 0xffffffff
|
||||
#define PIO_INT_MASK 0x08
|
||||
#define PIO_UNMASK(n) (1 << n)
|
||||
#define PIO_UNMASK_ALL 0xffffffff
|
||||
#define PIO_EDGECAPT 0x0c
|
||||
#define PIO_OUTSET 0x10
|
||||
#define PIO_OUTCLR 0x14
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#-
|
||||
# Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software was developed by SRI International and the University of
|
||||
# Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
# ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
INTERFACE pio;
|
||||
|
||||
#
|
||||
# PIO device methods
|
||||
#
|
||||
|
||||
METHOD int read {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
METHOD int setup_irq {
|
||||
device_t dev;
|
||||
void *handler;
|
||||
void *ih_user;
|
||||
};
|
||||
|
||||
METHOD int teardown_irq {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
METHOD int set {
|
||||
device_t dev;
|
||||
int bit;
|
||||
int enable;
|
||||
};
|
||||
|
||||
METHOD int configure {
|
||||
device_t dev;
|
||||
int dir;
|
||||
int mask;
|
||||
}
|
||||
|
|
@ -1,412 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_altera_sdcard.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/sdcard/altera_sdcard.h>
|
||||
|
||||
/*
|
||||
* Device driver for the Altera University Program Secure Data Card IP Core,
|
||||
* as described in the similarly named SOPC Builder IP Core specification.
|
||||
* This soft core is not a full SD host controller interface (SDHCI) but
|
||||
* instead provides a set of memory mapped registers and memory buffer that
|
||||
* mildly abstract the SD Card protocol, but without providing DMA or
|
||||
* interrupts. However, it does hide the details of voltage and
|
||||
* communications negotiation. This driver implements disk(9), but due to the
|
||||
* lack of interrupt support, must rely on timer-driven polling to determine
|
||||
* when I/Os have completed.
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* 1. Implement DISKFLAG_CANDELETE / SD Card sector erase support.
|
||||
* 2. Implement d_ident from SD Card CID serial number field.
|
||||
* 3. Handle read-only SD Cards.
|
||||
* 4. Tune timeouts based on real-world SD Card speeds.
|
||||
*/
|
||||
|
||||
void
|
||||
altera_sdcard_attach(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_INIT(sc);
|
||||
ALTERA_SDCARD_CONDVAR_INIT(sc);
|
||||
sc->as_disk = NULL;
|
||||
bioq_init(&sc->as_bioq);
|
||||
sc->as_currentbio = NULL;
|
||||
sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
|
||||
sc->as_taskqueue = taskqueue_create("altera_sdcardc taskq", M_WAITOK,
|
||||
taskqueue_thread_enqueue, &sc->as_taskqueue);
|
||||
taskqueue_start_threads(&sc->as_taskqueue, 1, PI_DISK,
|
||||
"altera_sdcardc%d taskqueue", sc->as_unit);
|
||||
TIMEOUT_TASK_INIT(sc->as_taskqueue, &sc->as_task, 0,
|
||||
altera_sdcard_task, sc);
|
||||
|
||||
/*
|
||||
* Kick off timer-driven processing with a manual poll so that we
|
||||
* synchronously detect an already-inserted SD Card during the boot or
|
||||
* other driver attach point.
|
||||
*/
|
||||
altera_sdcard_task(sc, 1);
|
||||
}
|
||||
|
||||
void
|
||||
altera_sdcard_detach(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
KASSERT(sc->as_taskqueue != NULL, ("%s: taskqueue not present",
|
||||
__func__));
|
||||
|
||||
/*
|
||||
* Winding down the driver on detach is a bit complex. Update the
|
||||
* flags to indicate that a detach has been requested, and then wait
|
||||
* for in-progress I/O to wind down before continuing.
|
||||
*/
|
||||
ALTERA_SDCARD_LOCK(sc);
|
||||
sc->as_flags |= ALTERA_SDCARD_FLAG_DETACHREQ;
|
||||
while (sc->as_state != ALTERA_SDCARD_STATE_DETACHED)
|
||||
ALTERA_SDCARD_CONDVAR_WAIT(sc);
|
||||
ALTERA_SDCARD_UNLOCK(sc);
|
||||
|
||||
/*
|
||||
* Now wait for the possibly still executing taskqueue to drain. In
|
||||
* principle no more events will be scheduled as we've transitioned to
|
||||
* a detached state, but there might still be a request in execution.
|
||||
*/
|
||||
while (taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL))
|
||||
taskqueue_drain_timeout(sc->as_taskqueue, &sc->as_task);
|
||||
|
||||
/*
|
||||
* Simulate a disk removal if one is present to deal with any pending
|
||||
* or queued I/O.
|
||||
*/
|
||||
if (sc->as_disk != NULL)
|
||||
altera_sdcard_disk_remove(sc);
|
||||
KASSERT(bioq_first(&sc->as_bioq) == NULL,
|
||||
("%s: non-empty bioq", __func__));
|
||||
|
||||
/*
|
||||
* Free any remaining allocated resources.
|
||||
*/
|
||||
taskqueue_free(sc->as_taskqueue);
|
||||
sc->as_taskqueue = NULL;
|
||||
ALTERA_SDCARD_CONDVAR_DESTROY(sc);
|
||||
ALTERA_SDCARD_LOCK_DESTROY(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up and start the next I/O. Transition to the I/O state, but allow the
|
||||
* caller to schedule the next timeout, as this may be called either from an
|
||||
* initial attach context, or from the task queue, which requires different
|
||||
* behaviour.
|
||||
*/
|
||||
static void
|
||||
altera_sdcard_nextio(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
struct bio *bp;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
KASSERT(sc->as_currentbio == NULL,
|
||||
("%s: bio already active", __func__));
|
||||
|
||||
bp = bioq_takefirst(&sc->as_bioq);
|
||||
if (bp == NULL)
|
||||
panic("%s: bioq empty", __func__);
|
||||
altera_sdcard_io_start(sc, bp);
|
||||
sc->as_state = ALTERA_SDCARD_STATE_IO;
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_task_nocard(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* Handle device driver detach.
|
||||
*/
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
|
||||
sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no card insertion, remain in NOCARD.
|
||||
*/
|
||||
if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Read the CSD -- it may contain values that the driver can't handle,
|
||||
* either because of an unsupported version/feature, or because the
|
||||
* card is misbehaving. This triggers a transition to
|
||||
* ALTERA_SDCARD_STATE_BADCARD. We rely on the CSD read to print a
|
||||
* banner about how the card is problematic, since it has more
|
||||
* information. The bad card state allows us to print that banner
|
||||
* once rather than each time we notice the card is there, and still
|
||||
* bad.
|
||||
*/
|
||||
if (altera_sdcard_read_csd(sc) != 0) {
|
||||
sc->as_state = ALTERA_SDCARD_STATE_BADCARD;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process card insertion and upgrade to the IDLE state.
|
||||
*/
|
||||
altera_sdcard_disk_insert(sc);
|
||||
sc->as_state = ALTERA_SDCARD_STATE_IDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_task_badcard(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* Handle device driver detach.
|
||||
*/
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
|
||||
sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle safe card removal -- no teardown is required, just a state
|
||||
* transition.
|
||||
*/
|
||||
if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
|
||||
sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_task_idle(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* Handle device driver detach.
|
||||
*/
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
|
||||
sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle safe card removal.
|
||||
*/
|
||||
if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT)) {
|
||||
altera_sdcard_disk_remove(sc);
|
||||
sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_task_io(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
uint16_t asr;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
KASSERT(sc->as_currentbio != NULL, ("%s: no current I/O", __func__));
|
||||
|
||||
#ifdef ALTERA_SDCARD_FAST_SIM
|
||||
recheck:
|
||||
#endif
|
||||
asr = altera_sdcard_read_asr(sc);
|
||||
|
||||
/*
|
||||
* Check for unexpected card removal during an I/O.
|
||||
*/
|
||||
if (!(asr & ALTERA_SDCARD_ASR_CARDPRESENT)) {
|
||||
altera_sdcard_disk_remove(sc);
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ)
|
||||
sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
|
||||
else
|
||||
sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the I/O isn't complete, remain in the IO state without further
|
||||
* action, even if DETACHREQ is in flight.
|
||||
*/
|
||||
if (asr & ALTERA_SDCARD_ASR_CMDINPROGRESS)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Handle various forms of I/O completion, successful and otherwise.
|
||||
* The I/O layer may restart the transaction if an error occurred, in
|
||||
* which case remain in the IO state and reschedule.
|
||||
*/
|
||||
if (!altera_sdcard_io_complete(sc, asr))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Now that I/O is complete, process detach requests in preference to
|
||||
* starting new I/O.
|
||||
*/
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
|
||||
sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, either start the next I/O or transition to the IDLE state.
|
||||
*/
|
||||
if (bioq_first(&sc->as_bioq) != NULL) {
|
||||
altera_sdcard_nextio(sc);
|
||||
#ifdef ALTERA_SDCARD_FAST_SIM
|
||||
goto recheck;
|
||||
#endif
|
||||
} else
|
||||
sc->as_state = ALTERA_SDCARD_STATE_IDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_task_rechedule(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
int interval;
|
||||
|
||||
/*
|
||||
* Reschedule based on new state. Or not, if detaching the device
|
||||
* driver. Treat a bad card as though it were no card at all.
|
||||
*/
|
||||
switch (sc->as_state) {
|
||||
case ALTERA_SDCARD_STATE_NOCARD:
|
||||
case ALTERA_SDCARD_STATE_BADCARD:
|
||||
interval = ALTERA_SDCARD_TIMEOUT_NOCARD;
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_IDLE:
|
||||
interval = ALTERA_SDCARD_TIMEOUT_IDLE;
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_IO:
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR)
|
||||
interval = ALTERA_SDCARD_TIMEOUT_IOERROR;
|
||||
else
|
||||
interval = ALTERA_SDCARD_TIMEOUT_IO;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: invalid exit state %d", __func__, sc->as_state);
|
||||
}
|
||||
taskqueue_enqueue_timeout(sc->as_taskqueue, &sc->as_task, interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because the Altera SD Card IP Core doesn't support interrupts, we do all
|
||||
* asynchronous work from a timeout. Poll at two different rates -- an
|
||||
* infrequent check for card insertion status changes, and a frequent one for
|
||||
* I/O completion. The task should never start in DETACHED, as that would
|
||||
* imply that a previous instance failed to cancel rather than reschedule.
|
||||
*/
|
||||
void
|
||||
altera_sdcard_task(void *arg, int pending)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
sc = arg;
|
||||
KASSERT(sc->as_state != ALTERA_SDCARD_STATE_DETACHED,
|
||||
("%s: already in detached", __func__));
|
||||
|
||||
ALTERA_SDCARD_LOCK(sc);
|
||||
switch (sc->as_state) {
|
||||
case ALTERA_SDCARD_STATE_NOCARD:
|
||||
altera_sdcard_task_nocard(sc);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_BADCARD:
|
||||
altera_sdcard_task_badcard(sc);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_IDLE:
|
||||
altera_sdcard_task_idle(sc);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_IO:
|
||||
altera_sdcard_task_io(sc);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: invalid enter state %d", __func__, sc->as_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have transitioned to DETACHED, signal the detach thread and
|
||||
* cancel the timeout-driven task. Otherwise reschedule on an
|
||||
* appropriate timeout.
|
||||
*/
|
||||
if (sc->as_state == ALTERA_SDCARD_STATE_DETACHED)
|
||||
ALTERA_SDCARD_CONDVAR_SIGNAL(sc);
|
||||
else
|
||||
altera_sdcard_task_rechedule(sc);
|
||||
ALTERA_SDCARD_UNLOCK(sc);
|
||||
}
|
||||
|
||||
void
|
||||
altera_sdcard_start(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(sc->as_state == ALTERA_SDCARD_STATE_IDLE,
|
||||
("%s: starting when not IDLE", __func__));
|
||||
|
||||
taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL);
|
||||
altera_sdcard_nextio(sc);
|
||||
#ifdef ALTERA_SDCARD_FAST_SIM
|
||||
altera_sdcard_task_io(sc);
|
||||
#endif
|
||||
altera_sdcard_task_rechedule(sc);
|
||||
}
|
||||
|
|
@ -1,247 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ALTERA_SDCARD_H_
|
||||
#define _DEV_ALTERA_SDCARD_H_
|
||||
|
||||
#define ALTERA_SDCARD_CSD_SIZE 16
|
||||
struct altera_sdcard_csd {
|
||||
uint8_t csd_data[ALTERA_SDCARD_CSD_SIZE];
|
||||
} __aligned(2); /* CSD is read in 16-bit chunks, so align to match. */
|
||||
|
||||
struct altera_sdcard_softc {
|
||||
device_t as_dev;
|
||||
int as_unit;
|
||||
struct resource *as_res;
|
||||
int as_rid;
|
||||
struct mtx as_lock;
|
||||
struct cv as_condvar;
|
||||
int as_state;
|
||||
int as_flags;
|
||||
struct disk *as_disk;
|
||||
struct taskqueue *as_taskqueue;
|
||||
struct timeout_task as_task;
|
||||
|
||||
/*
|
||||
* Fields relating to in-progress and pending I/O, if any.
|
||||
*/
|
||||
struct bio_queue_head as_bioq;
|
||||
struct bio *as_currentbio;
|
||||
u_int as_retriesleft;
|
||||
|
||||
/*
|
||||
* Infrequently changing fields cached from the SD Card IP Core.
|
||||
*/
|
||||
struct altera_sdcard_csd as_csd;
|
||||
uint8_t as_csd_structure; /* CSD version. */
|
||||
uint64_t as_mediasize;
|
||||
};
|
||||
|
||||
#define ALTERA_SDCARD_LOCK(sc) mtx_lock(&(sc)->as_lock)
|
||||
#define ALTERA_SDCARD_LOCK_ASSERT(sc) mtx_assert(&(sc)->as_lock, MA_OWNED)
|
||||
#define ALTERA_SDCARD_LOCK_DESTROY(sc) mtx_destroy(&(sc)->as_lock)
|
||||
#define ALTERA_SDCARD_LOCK_INIT(sc) mtx_init(&(sc)->as_lock, \
|
||||
"altera_sdcard", NULL, MTX_DEF)
|
||||
#define ALTERA_SDCARD_UNLOCK(sc) mtx_unlock(&(sc)->as_lock)
|
||||
|
||||
#define ALTERA_SDCARD_CONDVAR_DESTROY(sc) cv_destroy(&(sc)->as_condvar)
|
||||
#define ALTERA_SDCARD_CONDVAR_INIT(sc) cv_init(&(sc)->as_condvar, \
|
||||
"altera_sdcard_detach_wait")
|
||||
#define ALTERA_SDCARD_CONDVAR_SIGNAL(dc) cv_signal(&(sc)->as_condvar)
|
||||
#define ALTERA_SDCARD_CONDVAR_WAIT(sc) cv_wait(&(sc)->as_condvar, \
|
||||
&(sc)->as_lock)
|
||||
|
||||
/*
|
||||
* States an instance can be in at any given moment.
|
||||
*/
|
||||
#define ALTERA_SDCARD_STATE_NOCARD 1 /* No card inserted. */
|
||||
#define ALTERA_SDCARD_STATE_BADCARD 2 /* Card bad/not supported. */
|
||||
#define ALTERA_SDCARD_STATE_IDLE 3 /* Card present but idle. */
|
||||
#define ALTERA_SDCARD_STATE_IO 4 /* Card in I/O currently. */
|
||||
#define ALTERA_SDCARD_STATE_DETACHED 5 /* Driver is detaching. */
|
||||
|
||||
/*
|
||||
* Different timeout intervals based on state. When just looking for a card
|
||||
* status change, check twice a second. When we're actively waiting on I/O
|
||||
* completion, check every millisecond.
|
||||
*/
|
||||
#define ALTERA_SDCARD_TIMEOUT_NOCARD (hz/2)
|
||||
#define ALTERA_SDCARD_TIMEOUT_IDLE (hz/2)
|
||||
#define ALTERA_SDCARD_TIMEOUT_IO (1)
|
||||
#define ALTERA_SDCARD_TIMEOUT_IOERROR (hz/5)
|
||||
|
||||
/*
|
||||
* Maximum number of retries on an I/O.
|
||||
*/
|
||||
#define ALTERA_SDCARD_RETRY_LIMIT 10
|
||||
|
||||
/*
|
||||
* Driver status flags.
|
||||
*/
|
||||
#define ALTERA_SDCARD_FLAG_DETACHREQ 0x00000001 /* Detach requested. */
|
||||
#define ALTERA_SDCARD_FLAG_IOERROR 0x00000002 /* Error in progress. */
|
||||
|
||||
/*
|
||||
* Functions for performing low-level register and memory I/O to/from the SD
|
||||
* Card IP Core. In general, only code in altera_sdcard_io.c is aware of the
|
||||
* hardware interface.
|
||||
*/
|
||||
uint16_t altera_sdcard_read_asr(struct altera_sdcard_softc *sc);
|
||||
int altera_sdcard_read_csd(struct altera_sdcard_softc *sc);
|
||||
|
||||
int altera_sdcard_io_complete(struct altera_sdcard_softc *sc,
|
||||
uint16_t asr);
|
||||
void altera_sdcard_io_start(struct altera_sdcard_softc *sc,
|
||||
struct bio *bp);
|
||||
|
||||
/*
|
||||
* Constants for interpreting the SD Card Card Specific Data (CSD) register.
|
||||
*/
|
||||
#define ALTERA_SDCARD_CSD_STRUCTURE_BYTE 15
|
||||
#define ALTERA_SDCARD_CSD_STRUCTURE_MASK 0xc0 /* 2 bits */
|
||||
#define ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT 6
|
||||
|
||||
#define ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE 10
|
||||
#define ALTERA_SDCARD_CSD_READ_BL_LEN_MASK 0x0f /* 4 bits */
|
||||
|
||||
/*
|
||||
* C_SIZE is a 12-bit field helpfully split over three differe bytes of CSD
|
||||
* data. Software ease of use was not a design consideration.
|
||||
*/
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE0 7
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MASK0 0xc0 /* top 2 bits */
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0 6
|
||||
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE1 8
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MASK1 0xff /* 8 bits */
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1 2
|
||||
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE2 9
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MASK2 0x03 /* bottom 2 bits */
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2 10
|
||||
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0 5
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0 0x80 /* top 1 bit */
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0 7
|
||||
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1 6
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1 0x03 /* bottom 2 bits */
|
||||
#define ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1 1
|
||||
|
||||
/*
|
||||
* I/O register/buffer offsets, from Table 4.1.1 in the Altera University
|
||||
* Program SD Card IP Core specification.
|
||||
*/
|
||||
#define ALTERA_SDCARD_OFF_RXTX_BUFFER 0 /* 512-byte I/O buffer */
|
||||
#define ALTERA_SDCARD_OFF_CID 512 /* 16-byte Card ID number */
|
||||
#define ALTERA_SDCARD_OFF_CSD 528 /* 16-byte Card Specific Data */
|
||||
#define ALTERA_SDCARD_OFF_OCR 544 /* Operating Conditions Reg */
|
||||
#define ALTERA_SDCARD_OFF_SR 548 /* SD Card Status Register */
|
||||
#define ALTERA_SDCARD_OFF_RCA 552 /* Relative Card Address Reg */
|
||||
#define ALTERA_SDCARD_OFF_CMD_ARG 556 /* Command Argument Register */
|
||||
#define ALTERA_SDCARD_OFF_CMD 560 /* Command Register */
|
||||
#define ALTERA_SDCARD_OFF_ASR 564 /* Auxiliary Status Register */
|
||||
#define ALTERA_SDCARD_OFF_RR1 568 /* Response R1 */
|
||||
|
||||
/*
|
||||
* The Altera IP Core provides a 16-bit "Additional Status Register" (ASR)
|
||||
* beyond those described in the SD Card specification that captures IP Core
|
||||
* transaction state, such as whether the last command is in progress, the
|
||||
* card has been removed, etc.
|
||||
*/
|
||||
#define ALTERA_SDCARD_ASR_CMDVALID 0x0001
|
||||
#define ALTERA_SDCARD_ASR_CARDPRESENT 0x0002
|
||||
#define ALTERA_SDCARD_ASR_CMDINPROGRESS 0x0004
|
||||
#define ALTERA_SDCARD_ASR_SRVALID 0x0008
|
||||
#define ALTERA_SDCARD_ASR_CMDTIMEOUT 0x0010
|
||||
#define ALTERA_SDCARD_ASR_CMDDATAERROR 0x0020
|
||||
|
||||
/*
|
||||
* The Altera IP Core claims to provide a 16-bit "Response R1" register (RR1)
|
||||
* to provide more detailed error reporting when a read or write fails.
|
||||
*
|
||||
* XXXRW: The specification claims that this field is 16-bit, but then
|
||||
* proceeds to define values as though it is 32-bit. In practice, 16-bit
|
||||
* seems more likely as the register is not 32-bit aligned.
|
||||
*/
|
||||
#define ALTERA_SDCARD_RR1_INITPROCRUNNING 0x0100
|
||||
#define ALTERA_SDCARD_RR1_ERASEINTERRUPTED 0x0200
|
||||
#define ALTERA_SDCARD_RR1_ILLEGALCOMMAND 0x0400
|
||||
#define ALTERA_SDCARD_RR1_COMMANDCRCFAILED 0x0800
|
||||
#define ALTERA_SDCARD_RR1_ADDRESSMISALIGNED 0x1000
|
||||
#define ALTERA_SDCARD_RR1_ADDRBLOCKRANGE 0x2000
|
||||
|
||||
/*
|
||||
* Not all RR1 values are "errors" per se -- check only for the ones that are
|
||||
* when performing error handling.
|
||||
*/
|
||||
#define ALTERA_SDCARD_RR1_ERRORMASK \
|
||||
(ALTERA_SDCARD_RR1_ERASEINTERRUPTED | ALTERA_SDCARD_RR1_ILLEGALCOMMAND | \
|
||||
ALTERA_SDCARD_RR1_COMMANDCRCFAILED | ALTERA_SDCARD_RR1_ADDRESSMISALIGNED |\
|
||||
ALTERA_SDCARD_RR1_ADDRBLOCKRANGE)
|
||||
|
||||
/*
|
||||
* Although SD Cards may have various sector sizes, the Altera IP Core
|
||||
* requires that I/O be done in 512-byte chunks.
|
||||
*/
|
||||
#define ALTERA_SDCARD_SECTORSIZE 512
|
||||
|
||||
/*
|
||||
* SD Card commands used in this driver.
|
||||
*/
|
||||
#define ALTERA_SDCARD_CMD_SEND_RCA 0x03 /* Retrieve card RCA. */
|
||||
#define ALTERA_SDCARD_CMD_SEND_CSD 0x09 /* Retrieve CSD register. */
|
||||
#define ALTERA_SDCARD_CMD_SEND_CID 0x0A /* Retrieve CID register. */
|
||||
#define ALTERA_SDCARD_CMD_READ_BLOCK 0x11 /* Read block from disk. */
|
||||
#define ALTERA_SDCARD_CMD_WRITE_BLOCK 0x18 /* Write block to disk. */
|
||||
|
||||
/*
|
||||
* Functions exposed by the device driver core to newbus(9) bus attachment
|
||||
* implementations.
|
||||
*/
|
||||
void altera_sdcard_attach(struct altera_sdcard_softc *sc);
|
||||
void altera_sdcard_detach(struct altera_sdcard_softc *sc);
|
||||
void altera_sdcard_task(void *arg, int pending);
|
||||
|
||||
/*
|
||||
* Functions exposed by the device driver core to the disk(9) front-end.
|
||||
*/
|
||||
void altera_sdcard_start(struct altera_sdcard_softc *sc);
|
||||
|
||||
/*
|
||||
* Functions relating to the implementation of disk(9) KPIs for the SD Card
|
||||
* driver.
|
||||
*/
|
||||
void altera_sdcard_disk_insert(struct altera_sdcard_softc *sc);
|
||||
void altera_sdcard_disk_remove(struct altera_sdcard_softc *sc);
|
||||
|
||||
#endif /* _DEV_ALTERA_SDCARD_H_ */
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/sdcard/altera_sdcard.h>
|
||||
|
||||
static int
|
||||
altera_sdcard_disk_dump(void *arg, void *virtual, vm_offset_t physical,
|
||||
off_t offset, size_t length)
|
||||
{
|
||||
|
||||
panic("%s: not yet", __func__);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
/* XXXRW: more here? */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_disk_strategy(struct bio *bp)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
/*
|
||||
* Although the SD Card doesn't need sorting, we don't want to
|
||||
* introduce barriers, so use bioq_disksort().
|
||||
*/
|
||||
sc = bp->bio_disk->d_drv1;
|
||||
ALTERA_SDCARD_LOCK(sc);
|
||||
switch (sc->as_state) {
|
||||
case ALTERA_SDCARD_STATE_NOCARD:
|
||||
device_printf(sc->as_dev, "%s: unexpected I/O on NOCARD",
|
||||
__func__);
|
||||
biofinish(bp, NULL, ENXIO);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_BADCARD:
|
||||
device_printf(sc->as_dev, "%s: unexpected I/O on BADCARD",
|
||||
__func__);
|
||||
biofinish(bp, NULL, ENXIO);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_DETACHED:
|
||||
device_printf(sc->as_dev, "%s: unexpected I/O on DETACHED",
|
||||
__func__);
|
||||
biofinish(bp, NULL, ENXIO);
|
||||
|
||||
case ALTERA_SDCARD_STATE_IDLE:
|
||||
bioq_disksort(&sc->as_bioq, bp);
|
||||
altera_sdcard_start(sc);
|
||||
break;
|
||||
|
||||
case ALTERA_SDCARD_STATE_IO:
|
||||
bioq_disksort(&sc->as_bioq, bp);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: invalid state %d", __func__, sc->as_state);
|
||||
}
|
||||
ALTERA_SDCARD_UNLOCK(sc);
|
||||
}
|
||||
|
||||
void
|
||||
altera_sdcard_disk_insert(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
struct disk *disk;
|
||||
uint64_t size;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* Because the disk insertion routine occupies the driver instance's
|
||||
* task queue thread, and the disk(9) instance isn't hooked up yet by
|
||||
* definition, the only other source of events of concern is a thread
|
||||
* initiating driver detach. That thread has to issue a detach
|
||||
* request and await an ACK from the taskqueue thread. It is
|
||||
* therefore safe to drop the lock here.
|
||||
*/
|
||||
ALTERA_SDCARD_UNLOCK(sc);
|
||||
disk = disk_alloc();
|
||||
disk->d_drv1 = sc;
|
||||
disk->d_name = "altera_sdcard";
|
||||
disk->d_unit = sc->as_unit;
|
||||
disk->d_strategy = altera_sdcard_disk_strategy;
|
||||
disk->d_dump = altera_sdcard_disk_dump;
|
||||
disk->d_ioctl = altera_sdcard_disk_ioctl;
|
||||
disk->d_sectorsize = ALTERA_SDCARD_SECTORSIZE;
|
||||
disk->d_mediasize = sc->as_mediasize;
|
||||
disk->d_maxsize = ALTERA_SDCARD_SECTORSIZE;
|
||||
sc->as_disk = disk;
|
||||
disk_create(disk, DISK_VERSION);
|
||||
ALTERA_SDCARD_LOCK(sc);
|
||||
|
||||
/*
|
||||
* Print a pretty-ish card insertion string. We could stand to
|
||||
* decorate this further, e.g., with card vendor information.
|
||||
*/
|
||||
size = sc->as_mediasize / (1000 * 1000);
|
||||
device_printf(sc->as_dev, "%juM SD Card inserted\n", (uintmax_t)size);
|
||||
}
|
||||
|
||||
void
|
||||
altera_sdcard_disk_remove(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
struct disk *disk;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
KASSERT(sc->as_disk != NULL, ("%s: as_disk NULL", __func__));
|
||||
|
||||
/*
|
||||
* sc->as_state will be updated by the caller.
|
||||
*
|
||||
* XXXRW: Is it OK to call disk_destroy() under the mutex, or should
|
||||
* we be deferring that to the calling context once it is released?
|
||||
*/
|
||||
disk = sc->as_disk;
|
||||
disk_gone(disk);
|
||||
disk_destroy(disk);
|
||||
sc->as_disk = NULL;
|
||||
|
||||
/*
|
||||
* Cancel all outstanding I/O on the SD Card.
|
||||
*/
|
||||
if (sc->as_currentbio != NULL) {
|
||||
device_printf(sc->as_dev, "%s: SD Card removed during I/O",
|
||||
__func__);
|
||||
biofinish(sc->as_currentbio, NULL, ENXIO);
|
||||
sc->as_currentbio = NULL;
|
||||
}
|
||||
bioq_flush(&sc->as_bioq, NULL, ENXIO);
|
||||
device_printf(sc->as_dev, "SD Card removed\n");
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/sdcard/altera_sdcard.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
/*
|
||||
* FDT bus attachment for the Altera SD Card IP core.
|
||||
*/
|
||||
static int
|
||||
altera_sdcard_fdt_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "altera,sdcard_11_2011")) {
|
||||
device_set_desc(dev, "Altera Secure Data Card IP Core");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_fdt_attach(device_t dev)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->as_dev = dev;
|
||||
sc->as_unit = device_get_unit(dev);
|
||||
sc->as_rid = 0;
|
||||
sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->as_rid, RF_ACTIVE);
|
||||
if (sc->as_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
altera_sdcard_attach(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_fdt_detach(device_t dev)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
|
||||
__func__));
|
||||
altera_sdcard_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_sdcard_fdt_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_sdcard_fdt_probe),
|
||||
DEVMETHOD(device_attach, altera_sdcard_fdt_attach),
|
||||
DEVMETHOD(device_detach, altera_sdcard_fdt_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_sdcard_fdt_driver = {
|
||||
"altera_sdcardc",
|
||||
altera_sdcard_fdt_methods,
|
||||
sizeof(struct altera_sdcard_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(altera_sdcard, simplebus, altera_sdcard_fdt_driver, 0, 0);
|
||||
|
|
@ -1,446 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/sdcard/altera_sdcard.h>
|
||||
|
||||
int altera_sdcard_ignore_crc_errors = 1;
|
||||
int altera_sdcard_verify_rxtx_writes = 1;
|
||||
|
||||
/*
|
||||
* Low-level I/O routines for the Altera SD Card University IP Core driver.
|
||||
*
|
||||
* XXXRW: Throughout, it is assumed that the IP Core handles multibyte
|
||||
* registers as little endian, as is the case for other Altera IP cores.
|
||||
* However, the specification makes no reference to endianness, so this
|
||||
* assumption might not always be correct.
|
||||
*/
|
||||
uint16_t
|
||||
altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
uint64_t c_size, c_size_mult, read_bl_len;
|
||||
uint8_t byte0, byte1, byte2;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*-
|
||||
* Compute card capacity per SD Card interface description as follows:
|
||||
*
|
||||
* Memory capacity = BLOCKNR * BLOCK_LEN
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* BLOCKNR = (C_SIZE + 1) * MULT
|
||||
* MULT = 2^(C_SIZE_MULT+2)
|
||||
* BLOCK_LEN = 2^READ_BL_LEN
|
||||
*/
|
||||
read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
|
||||
read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
|
||||
|
||||
byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
|
||||
byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
|
||||
byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
|
||||
byte2 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE2];
|
||||
byte2 &= ALTERA_SDCARD_CSD_C_SIZE_MASK2;
|
||||
c_size = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0) |
|
||||
(byte1 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1) |
|
||||
(byte2 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2);
|
||||
|
||||
byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
|
||||
byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
|
||||
byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
|
||||
byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
|
||||
c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
|
||||
(byte1 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
|
||||
|
||||
/*
|
||||
* If we're just getting back zero's, mark the card as bad, even
|
||||
* though it could just mean a Very Small Disk Indeed.
|
||||
*/
|
||||
if (c_size == 0 && c_size_mult == 0 && read_bl_len == 0) {
|
||||
device_printf(sc->as_dev, "Ignored zero-size card\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->as_mediasize = (c_size + 1) * (1 << (c_size_mult + 2)) *
|
||||
(1 << read_bl_len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
altera_sdcard_read_csd(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
uint8_t csd_structure;
|
||||
int error;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* XXXRW: Assume for now that when the SD Card IP Core negotiates
|
||||
* voltage/speed/etc, it must use the CSD register, and therefore
|
||||
* populates the SD Card IP Core's cache of the register value. This
|
||||
* means that we can read it without issuing further SD Card commands.
|
||||
* If this assumption proves false, we will (a) get back garbage and
|
||||
* (b) need to add additional states in the driver state machine in
|
||||
* order to query card properties before I/O can start.
|
||||
*
|
||||
* XXXRW: Treating this as an array of bytes, so no byte swapping --
|
||||
* is that a safe assumption?
|
||||
*/
|
||||
KASSERT(((uintptr_t)&sc->as_csd.csd_data) % 2 == 0,
|
||||
("%s: CSD buffer unaligned", __func__));
|
||||
bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_CSD,
|
||||
(uint16_t *)sc->as_csd.csd_data, sizeof(sc->as_csd) / 2);
|
||||
|
||||
/*
|
||||
* Interpret the loaded CSD, extracting certain fields and copying
|
||||
* them into the softc for easy software access.
|
||||
*
|
||||
* Currently, we support only CSD Version 1.0. If we detect a newer
|
||||
* version, suppress card detection.
|
||||
*/
|
||||
csd_structure = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_STRUCTURE_BYTE];
|
||||
csd_structure &= ALTERA_SDCARD_CSD_STRUCTURE_MASK;
|
||||
csd_structure >>= ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT;
|
||||
sc->as_csd_structure = csd_structure;
|
||||
|
||||
/*
|
||||
* Interpret the CSD field based on its version. Extract fields,
|
||||
* especially mediasize.
|
||||
*
|
||||
* XXXRW: Desirable to support further CSD versions here.
|
||||
*/
|
||||
switch (sc->as_csd_structure) {
|
||||
case 0:
|
||||
error = altera_sdcard_process_csd0(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(sc->as_dev,
|
||||
"Ignored disk with unsupported CSD structure (%d)\n",
|
||||
sc->as_csd_structure);
|
||||
return (ENXIO);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXRW: The Altera IP Core specification indicates that RR1 is a 16-bit
|
||||
* register, but all bits it identifies are >16 bit. Most likely, RR1 is a
|
||||
* 32-bit register?
|
||||
*/
|
||||
static uint16_t
|
||||
altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
|
||||
{
|
||||
|
||||
return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
|
||||
{
|
||||
|
||||
bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
|
||||
{
|
||||
|
||||
bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD, htole16(cmd));
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
|
||||
size_t len)
|
||||
{
|
||||
|
||||
KASSERT((uintptr_t)data % 2 == 0,
|
||||
("%s: unaligned data %p", __func__, data));
|
||||
KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
|
||||
("%s: invalid length %ju", __func__, len));
|
||||
|
||||
bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
|
||||
(uint16_t *)data, len / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
|
||||
size_t len)
|
||||
{
|
||||
u_int corrections, differences, i, retry_counter;
|
||||
uint16_t d, v;
|
||||
|
||||
KASSERT((uintptr_t)data % 2 == 0,
|
||||
("%s: unaligned data %p", __func__, data));
|
||||
KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
|
||||
("%s: invalid length %ju", __func__, len));
|
||||
|
||||
retry_counter = 0;
|
||||
do {
|
||||
bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
|
||||
(uint16_t *)data, len / 2);
|
||||
|
||||
/*
|
||||
* XXXRW: Due to a possible hardware bug, the above call to
|
||||
* bus_write_region_2() might not succeed. If the workaround
|
||||
* is enabled, verify each write and retry until it succeeds.
|
||||
*
|
||||
* XXXRW: Do we want a limit counter for retries here?
|
||||
*/
|
||||
recheck:
|
||||
corrections = 0;
|
||||
differences = 0;
|
||||
if (altera_sdcard_verify_rxtx_writes) {
|
||||
for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) {
|
||||
v = bus_read_2(sc->as_res,
|
||||
ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
|
||||
d = *(uint16_t *)((uint8_t *)data + i);
|
||||
if (v != d) {
|
||||
if (retry_counter == 0) {
|
||||
bus_write_2(sc->as_res,
|
||||
ALTERA_SDCARD_OFF_RXTX_BUFFER + i,
|
||||
d);
|
||||
v = bus_read_2(sc->as_res,
|
||||
ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
|
||||
if (v == d) {
|
||||
corrections++;
|
||||
device_printf(sc->as_dev,
|
||||
"%s: single word rewrite worked"
|
||||
" at offset %u\n",
|
||||
__func__, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
differences++;
|
||||
device_printf(sc->as_dev,
|
||||
"%s: retrying write -- difference"
|
||||
" %u at offset %u, retry %u\n",
|
||||
__func__, differences, i,
|
||||
retry_counter);
|
||||
}
|
||||
}
|
||||
if (differences != 0) {
|
||||
retry_counter++;
|
||||
if (retry_counter == 1 &&
|
||||
corrections == differences)
|
||||
goto recheck;
|
||||
}
|
||||
}
|
||||
} while (differences != 0);
|
||||
if (retry_counter)
|
||||
device_printf(sc->as_dev, "%s: succeeded after %u retries\n",
|
||||
__func__, retry_counter);
|
||||
}
|
||||
|
||||
static void
|
||||
altera_sdcard_io_start_internal(struct altera_sdcard_softc *sc,
|
||||
struct bio **bpp)
|
||||
{
|
||||
struct bio *bp;
|
||||
|
||||
bp = *bpp;
|
||||
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
|
||||
ALTERA_SDCARD_SECTORSIZE);
|
||||
altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
|
||||
break;
|
||||
|
||||
case BIO_WRITE:
|
||||
altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
|
||||
bp->bio_bcount);
|
||||
altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
|
||||
ALTERA_SDCARD_SECTORSIZE);
|
||||
altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
|
||||
break;
|
||||
|
||||
default:
|
||||
biofinish(bp, NULL, EOPNOTSUPP);
|
||||
*bpp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
|
||||
{
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
KASSERT(sc->as_currentbio == NULL,
|
||||
("%s: bio already started", __func__));
|
||||
|
||||
/*
|
||||
* We advertise a block size and maximum I/O size up the stack of the
|
||||
* SD Card IP Core sector size. Catch any attempts to not follow the
|
||||
* rules.
|
||||
*/
|
||||
KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
|
||||
("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
|
||||
altera_sdcard_io_start_internal(sc, &bp);
|
||||
sc->as_currentbio = bp;
|
||||
sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle completed I/O. ASR is passed in to avoid reading it more than once.
|
||||
* Return 1 if the I/O is actually complete (success, or retry limit
|
||||
* exceeded), or 0 if not.
|
||||
*/
|
||||
int
|
||||
altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
|
||||
{
|
||||
struct bio *bp;
|
||||
uint16_t rr1, mask;
|
||||
int error;
|
||||
|
||||
ALTERA_SDCARD_LOCK_ASSERT(sc);
|
||||
KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
|
||||
("%s: still in progress", __func__));
|
||||
KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
|
||||
("%s: card removed", __func__));
|
||||
|
||||
bp = sc->as_currentbio;
|
||||
|
||||
/*-
|
||||
* Handle I/O retries if an error is returned by the device. Various
|
||||
* quirks handled in the process:
|
||||
*
|
||||
* 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE.
|
||||
* 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for
|
||||
* BIO_READ.
|
||||
*/
|
||||
error = 0;
|
||||
rr1 = altera_sdcard_read_rr1(sc);
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
mask = ALTERA_SDCARD_RR1_ERRORMASK;
|
||||
if (altera_sdcard_ignore_crc_errors)
|
||||
mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED;
|
||||
if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
|
||||
error = EIO;
|
||||
else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) &&
|
||||
(rr1 & mask))
|
||||
error = EIO;
|
||||
else
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case BIO_WRITE:
|
||||
if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
|
||||
error = EIO;
|
||||
else
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (error) {
|
||||
sc->as_retriesleft--;
|
||||
if (sc->as_retriesleft == 0 || bootverbose)
|
||||
device_printf(sc->as_dev, "%s: %s operation block %ju "
|
||||
"length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n",
|
||||
__func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
|
||||
(bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" :
|
||||
"unknown"),
|
||||
bp->bio_pblkno, bp->bio_bcount, asr, rr1,
|
||||
sc->as_retriesleft != 0 ? " retrying" : "");
|
||||
/*
|
||||
* This attempt experienced an error; possibly retry.
|
||||
*/
|
||||
if (sc->as_retriesleft != 0) {
|
||||
sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR;
|
||||
altera_sdcard_io_start_internal(sc, &bp);
|
||||
return (0);
|
||||
}
|
||||
sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
|
||||
} else {
|
||||
/*
|
||||
* Successful I/O completion path.
|
||||
*/
|
||||
if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) {
|
||||
device_printf(sc->as_dev, "%s: %s operation block %ju"
|
||||
" length %ju succeeded after %d retries\n",
|
||||
__func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
|
||||
(bp->bio_cmd == BIO_WRITE ? "write" : "unknown"),
|
||||
bp->bio_pblkno, bp->bio_bcount,
|
||||
ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft);
|
||||
sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
|
||||
}
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
|
||||
bp->bio_bcount);
|
||||
break;
|
||||
|
||||
case BIO_WRITE:
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: unsupported I/O operation %d", __func__,
|
||||
bp->bio_cmd);
|
||||
}
|
||||
bp->bio_resid = 0;
|
||||
error = 0;
|
||||
}
|
||||
biofinish(bp, NULL, error);
|
||||
sc->as_currentbio = NULL;
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
#include <dev/altera/sdcard/altera_sdcard.h>
|
||||
|
||||
/*
|
||||
* Nexus bus attachment for the Altera SD Card IP core. Appropriate for most
|
||||
* Altera FPGA SoC-style configurations in which the IP core will be exposed
|
||||
* to the processor via a memory-mapped Avalon bus.
|
||||
*/
|
||||
static int
|
||||
altera_sdcard_nexus_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "Altera Secure Data Card IP Core");
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_nexus_attach(device_t dev)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->as_dev = dev;
|
||||
sc->as_unit = device_get_unit(dev);
|
||||
sc->as_rid = 0;
|
||||
sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->as_rid, RF_ACTIVE);
|
||||
if (sc->as_res == NULL) {
|
||||
device_printf(dev, "couldn't map memory\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
altera_sdcard_attach(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
altera_sdcard_nexus_detach(device_t dev)
|
||||
{
|
||||
struct altera_sdcard_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
|
||||
__func__));
|
||||
altera_sdcard_detach(sc);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t altera_sdcard_nexus_methods[] = {
|
||||
DEVMETHOD(device_probe, altera_sdcard_nexus_probe),
|
||||
DEVMETHOD(device_attach, altera_sdcard_nexus_attach),
|
||||
DEVMETHOD(device_detach, altera_sdcard_nexus_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t altera_sdcard_nexus_driver = {
|
||||
"altera_sdcardc",
|
||||
altera_sdcard_nexus_methods,
|
||||
sizeof(struct altera_sdcard_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(altera_sdcard, nexus, altera_sdcard_nexus_driver, 0, 0);
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2012 Bjoern A. Zeeb
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
|
||||
* ("MRC2"), as part of the DARPA MRC research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* Altera, Embedded Peripherals IP, User Guide, v. 11.0, June 2011.
|
||||
* UG-01085-11.0.
|
||||
*/
|
||||
|
||||
#ifndef _A_API_H
|
||||
#define _A_API_H
|
||||
|
||||
/* Table 16-1. Memory Map. */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_DATA 0x00
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_METADATA 0x04
|
||||
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_SOP (1<<0)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EOP (1<<1)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK 0x000000f7
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT 2
|
||||
/* Reserved (1<<7) */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK 0x0000ff00
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT 8
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK 0x00ff0000
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT 16
|
||||
/* Reserved 0xff000000 */
|
||||
|
||||
/* Table 16-3. FIFO Status Register Memory Map. */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL 0x00
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS 0x04
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT 0x08
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE 0x0c
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTFULL 0x10
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTEMPTY 0x14
|
||||
|
||||
/* Table 16-5. Status Bit Field Descriptions. */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_FULL (1<<0)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_EMPTY (1<<1)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTFULL (1<<2)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTEMPTY (1<<3)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_OVERFLOW (1<<4)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_STATUS_UNDERFLOW (1<<5)
|
||||
|
||||
/* Table 16-6. Event Bit Field Descriptions. */
|
||||
/* XXX Datasheet has incorrect bit fields. Validate. */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_FULL (1<<0)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_EMPTY (1<<1)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTFULL (1<<2)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTEMPTY (1<<3)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW (1<<4)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW (1<<5)
|
||||
|
||||
/* Table 16-7. InterruptEnable Bit Field Descriptions. */
|
||||
/* XXX Datasheet has incorrect bit fields. Validate. */
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_FULL (1<<0)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY (1<<1)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL (1<<2)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY (1<<3)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW (1<<4)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW (1<<5)
|
||||
#define A_ONCHIP_FIFO_MEM_CORE_INTR_ALL \
|
||||
(A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY| \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_FULL| \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY| \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL| \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW| \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
|
||||
|
||||
#endif /* _A_API_H */
|
||||
|
||||
/* end */
|
||||
|
|
@ -1,882 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is driver for SoftDMA device built using Altera FIFO component. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_platform.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#endif
|
||||
|
||||
#include <dev/altera/softdma/a_api.h>
|
||||
|
||||
#include <dev/xdma/xdma.h>
|
||||
#include "xdma_if.h"
|
||||
|
||||
#define SOFTDMA_DEBUG
|
||||
#undef SOFTDMA_DEBUG
|
||||
|
||||
#ifdef SOFTDMA_DEBUG
|
||||
#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define AVALON_FIFO_TX_BASIC_OPTS_DEPTH 16
|
||||
#define SOFTDMA_NCHANNELS 1
|
||||
#define CONTROL_GEN_SOP (1 << 0)
|
||||
#define CONTROL_GEN_EOP (1 << 1)
|
||||
#define CONTROL_OWN (1 << 31)
|
||||
|
||||
#define SOFTDMA_RX_EVENTS \
|
||||
(A_ONCHIP_FIFO_MEM_CORE_INTR_FULL | \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
|
||||
#define SOFTDMA_TX_EVENTS \
|
||||
(A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY | \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
|
||||
A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
|
||||
|
||||
struct softdma_channel {
|
||||
struct softdma_softc *sc;
|
||||
struct mtx mtx;
|
||||
xdma_channel_t *xchan;
|
||||
struct proc *p;
|
||||
int used;
|
||||
int index;
|
||||
int run;
|
||||
uint32_t idx_tail;
|
||||
uint32_t idx_head;
|
||||
struct softdma_desc *descs;
|
||||
|
||||
uint32_t descs_num;
|
||||
uint32_t descs_used_count;
|
||||
};
|
||||
|
||||
struct softdma_desc {
|
||||
uint64_t src_addr;
|
||||
uint64_t dst_addr;
|
||||
uint32_t len;
|
||||
uint32_t access_width;
|
||||
uint32_t count;
|
||||
uint16_t src_incr;
|
||||
uint16_t dst_incr;
|
||||
uint32_t direction;
|
||||
struct softdma_desc *next;
|
||||
uint32_t transfered;
|
||||
uint32_t status;
|
||||
uint32_t reserved;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
struct softdma_softc {
|
||||
device_t dev;
|
||||
struct resource *res[3];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_space_tag_t bst_c;
|
||||
bus_space_handle_t bsh_c;
|
||||
void *ih;
|
||||
struct softdma_channel channels[SOFTDMA_NCHANNELS];
|
||||
};
|
||||
|
||||
static struct resource_spec softdma_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* fifo */
|
||||
{ SYS_RES_MEMORY, 1, RF_ACTIVE }, /* core */
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int softdma_probe(device_t dev);
|
||||
static int softdma_attach(device_t dev);
|
||||
static int softdma_detach(device_t dev);
|
||||
|
||||
static inline uint32_t
|
||||
softdma_next_desc(struct softdma_channel *chan, uint32_t curidx)
|
||||
{
|
||||
|
||||
return ((curidx + 1) % chan->descs_num);
|
||||
}
|
||||
|
||||
static void
|
||||
softdma_mem_write(struct softdma_softc *sc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
|
||||
bus_write_4(sc->res[0], reg, htole32(val));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
softdma_mem_read(struct softdma_softc *sc, uint32_t reg)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = bus_read_4(sc->res[0], reg);
|
||||
|
||||
return (le32toh(val));
|
||||
}
|
||||
|
||||
static void
|
||||
softdma_memc_write(struct softdma_softc *sc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
|
||||
bus_write_4(sc->res[1], reg, htole32(val));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
softdma_memc_read(struct softdma_softc *sc, uint32_t reg)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = bus_read_4(sc->res[1], reg);
|
||||
|
||||
return (le32toh(val));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
softdma_fill_level(struct softdma_softc *sc)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = softdma_memc_read(sc,
|
||||
A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
fifo_fill_level_wait(struct softdma_softc *sc)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
do
|
||||
val = softdma_fill_level(sc);
|
||||
while (val == AVALON_FIFO_TX_BASIC_OPTS_DEPTH);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static void
|
||||
softdma_intr(void *arg)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_softc *sc;
|
||||
int reg;
|
||||
int err;
|
||||
|
||||
sc = arg;
|
||||
|
||||
chan = &sc->channels[0];
|
||||
|
||||
reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT);
|
||||
|
||||
if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW |
|
||||
A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
|
||||
/* Errors */
|
||||
err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \
|
||||
A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
|
||||
}
|
||||
|
||||
if (reg != 0) {
|
||||
softdma_memc_write(sc,
|
||||
A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg);
|
||||
chan->run = 1;
|
||||
wakeup(chan);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "altr,softdma"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "SoftDMA");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_attach(device_t dev)
|
||||
{
|
||||
struct softdma_softc *sc;
|
||||
phandle_t xref, node;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, softdma_spec, sc->res)) {
|
||||
device_printf(dev,
|
||||
"could not allocate resources for device\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* FIFO memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
/* FIFO control memory interface */
|
||||
sc->bst_c = rman_get_bustag(sc->res[1]);
|
||||
sc->bsh_c = rman_get_bushandle(sc->res[1]);
|
||||
|
||||
/* Setup interrupt handler */
|
||||
err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, softdma_intr, sc, &sc->ih);
|
||||
if (err) {
|
||||
device_printf(dev, "Unable to alloc interrupt resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
xref = OF_xref_from_node(node);
|
||||
OF_device_register_xref(xref, dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_detach(device_t dev)
|
||||
{
|
||||
struct softdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc)
|
||||
{
|
||||
struct softdma_softc *sc;
|
||||
uint64_t addr;
|
||||
uint64_t buf;
|
||||
uint32_t word;
|
||||
uint32_t missing;
|
||||
uint32_t reg;
|
||||
int got_bits;
|
||||
int len;
|
||||
|
||||
sc = chan->sc;
|
||||
|
||||
fifo_fill_level_wait(sc);
|
||||
|
||||
/* Set start of packet. */
|
||||
if (desc->control & CONTROL_GEN_SOP)
|
||||
softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
|
||||
A_ONCHIP_FIFO_MEM_CORE_SOP);
|
||||
|
||||
got_bits = 0;
|
||||
buf = 0;
|
||||
|
||||
addr = desc->src_addr;
|
||||
len = desc->len;
|
||||
|
||||
if (addr & 1) {
|
||||
buf = (buf << 8) | *(uint8_t *)addr;
|
||||
got_bits += 8;
|
||||
addr += 1;
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
if (len >= 2 && addr & 2) {
|
||||
buf = (buf << 16) | *(uint16_t *)addr;
|
||||
got_bits += 16;
|
||||
addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
while (len >= 4) {
|
||||
buf = (buf << 32) | (uint64_t)*(uint32_t *)addr;
|
||||
addr += 4;
|
||||
len -= 4;
|
||||
word = (uint32_t)((buf >> got_bits) & 0xffffffff);
|
||||
|
||||
fifo_fill_level_wait(sc);
|
||||
if (len == 0 && got_bits == 0 &&
|
||||
(desc->control & CONTROL_GEN_EOP) != 0)
|
||||
softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
|
||||
A_ONCHIP_FIFO_MEM_CORE_EOP);
|
||||
bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
|
||||
}
|
||||
|
||||
if (len & 2) {
|
||||
buf = (buf << 16) | *(uint16_t *)addr;
|
||||
got_bits += 16;
|
||||
addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
if (len & 1) {
|
||||
buf = (buf << 8) | *(uint8_t *)addr;
|
||||
got_bits += 8;
|
||||
addr += 1;
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
if (got_bits >= 32) {
|
||||
got_bits -= 32;
|
||||
word = (uint32_t)((buf >> got_bits) & 0xffffffff);
|
||||
|
||||
fifo_fill_level_wait(sc);
|
||||
if (len == 0 && got_bits == 0 &&
|
||||
(desc->control & CONTROL_GEN_EOP) != 0)
|
||||
softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
|
||||
A_ONCHIP_FIFO_MEM_CORE_EOP);
|
||||
bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
|
||||
}
|
||||
|
||||
if (got_bits) {
|
||||
missing = 32 - got_bits;
|
||||
got_bits /= 8;
|
||||
|
||||
fifo_fill_level_wait(sc);
|
||||
reg = A_ONCHIP_FIFO_MEM_CORE_EOP |
|
||||
((4 - got_bits) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
|
||||
softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
|
||||
word = (uint32_t)((buf << missing) & 0xffffffff);
|
||||
bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
|
||||
}
|
||||
|
||||
return (desc->len);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc)
|
||||
{
|
||||
uint32_t src_offs, dst_offs;
|
||||
struct softdma_softc *sc;
|
||||
uint32_t fill_level;
|
||||
uint32_t empty;
|
||||
uint32_t meta;
|
||||
uint32_t data;
|
||||
int sop_rcvd;
|
||||
int timeout;
|
||||
size_t len;
|
||||
int error;
|
||||
|
||||
sc = chan->sc;
|
||||
empty = 0;
|
||||
src_offs = dst_offs = 0;
|
||||
error = 0;
|
||||
|
||||
fill_level = softdma_fill_level(sc);
|
||||
if (fill_level == 0) {
|
||||
/* Nothing to receive. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
len = desc->len;
|
||||
|
||||
sop_rcvd = 0;
|
||||
while (fill_level) {
|
||||
empty = 0;
|
||||
data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA);
|
||||
meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA);
|
||||
|
||||
if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
|
||||
sop_rcvd = 1;
|
||||
}
|
||||
|
||||
if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
|
||||
empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
|
||||
A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
|
||||
}
|
||||
|
||||
if (sop_rcvd == 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty == 0) {
|
||||
*(uint32_t *)(desc->dst_addr + dst_offs) = data;
|
||||
dst_offs += 4;
|
||||
} else if (empty == 1) {
|
||||
*(uint16_t *)(desc->dst_addr + dst_offs) =
|
||||
((data >> 16) & 0xffff);
|
||||
dst_offs += 2;
|
||||
|
||||
*(uint8_t *)(desc->dst_addr + dst_offs) =
|
||||
((data >> 8) & 0xff);
|
||||
dst_offs += 1;
|
||||
} else {
|
||||
panic("empty %d\n", empty);
|
||||
}
|
||||
|
||||
if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP)
|
||||
break;
|
||||
|
||||
fill_level = softdma_fill_level(sc);
|
||||
timeout = 100;
|
||||
while (fill_level == 0 && timeout--)
|
||||
fill_level = softdma_fill_level(sc);
|
||||
if (timeout == 0) {
|
||||
/* No EOP received. Broken packet. */
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (dst_offs);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
softdma_process_descriptors(struct softdma_channel *chan,
|
||||
xdma_transfer_status_t *status)
|
||||
{
|
||||
struct xdma_channel *xchan;
|
||||
struct softdma_desc *desc;
|
||||
struct softdma_softc *sc;
|
||||
xdma_transfer_status_t st;
|
||||
int ret;
|
||||
|
||||
sc = chan->sc;
|
||||
|
||||
xchan = chan->xchan;
|
||||
|
||||
desc = &chan->descs[chan->idx_tail];
|
||||
|
||||
while (desc != NULL) {
|
||||
if ((desc->control & CONTROL_OWN) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc->direction == XDMA_MEM_TO_DEV) {
|
||||
ret = softdma_process_tx(chan, desc);
|
||||
} else {
|
||||
ret = softdma_process_rx(chan, desc);
|
||||
if (ret == 0) {
|
||||
/* No new data available. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Descriptor processed. */
|
||||
desc->control = 0;
|
||||
|
||||
if (ret >= 0) {
|
||||
st.error = 0;
|
||||
st.transferred = ret;
|
||||
} else {
|
||||
st.error = ret;
|
||||
st.transferred = 0;
|
||||
}
|
||||
|
||||
xchan_seg_done(xchan, &st);
|
||||
atomic_subtract_int(&chan->descs_used_count, 1);
|
||||
|
||||
if (ret >= 0) {
|
||||
status->transferred += ret;
|
||||
} else {
|
||||
status->error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
chan->idx_tail = softdma_next_desc(chan, chan->idx_tail);
|
||||
|
||||
/* Process next descriptor, if any. */
|
||||
desc = desc->next;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
softdma_worker(void *arg)
|
||||
{
|
||||
xdma_transfer_status_t status;
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_softc *sc;
|
||||
|
||||
chan = arg;
|
||||
|
||||
sc = chan->sc;
|
||||
|
||||
while (1) {
|
||||
mtx_lock(&chan->mtx);
|
||||
|
||||
do {
|
||||
mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2);
|
||||
} while (chan->run == 0);
|
||||
|
||||
status.error = 0;
|
||||
status.transferred = 0;
|
||||
|
||||
softdma_process_descriptors(chan, &status);
|
||||
|
||||
/* Finish operation */
|
||||
chan->run = 0;
|
||||
xdma_callback(chan->xchan, &status);
|
||||
|
||||
mtx_unlock(&chan->mtx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_proc_create(struct softdma_channel *chan)
|
||||
{
|
||||
struct softdma_softc *sc;
|
||||
|
||||
sc = chan->sc;
|
||||
|
||||
if (chan->p != NULL) {
|
||||
/* Already created */
|
||||
return (0);
|
||||
}
|
||||
|
||||
mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF);
|
||||
|
||||
if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0,
|
||||
"softdma_worker") != 0) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Failed to create worker thread.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_alloc(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_softc *sc;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
for (i = 0; i < SOFTDMA_NCHANNELS; i++) {
|
||||
chan = &sc->channels[i];
|
||||
if (chan->used == 0) {
|
||||
chan->xchan = xchan;
|
||||
xchan->chan = (void *)chan;
|
||||
xchan->caps |= XCHAN_CAP_NOSEG;
|
||||
chan->index = i;
|
||||
chan->idx_head = 0;
|
||||
chan->idx_tail = 0;
|
||||
chan->descs_used_count = 0;
|
||||
chan->descs_num = 1024;
|
||||
chan->sc = sc;
|
||||
|
||||
if (softdma_proc_create(chan) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
chan->used = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_free(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
if (chan->descs != NULL) {
|
||||
free(chan->descs, M_DEVBUF);
|
||||
}
|
||||
|
||||
chan->used = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_desc_alloc(struct xdma_channel *xchan)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
uint32_t nsegments;
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
nsegments = chan->descs_num;
|
||||
|
||||
chan->descs = malloc(nsegments * sizeof(struct softdma_desc),
|
||||
M_DEVBUF, (M_WAITOK | M_ZERO));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_desc *desc;
|
||||
struct softdma_softc *sc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
ret = softdma_desc_alloc(xchan);
|
||||
if (ret != 0) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't allocate descriptors.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < chan->descs_num; i++) {
|
||||
desc = &chan->descs[i];
|
||||
|
||||
if (i == (chan->descs_num - 1)) {
|
||||
desc->next = &chan->descs[0];
|
||||
} else {
|
||||
desc->next = &chan->descs[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_capacity(device_t dev, xdma_channel_t *xchan,
|
||||
uint32_t *capacity)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
uint32_t c;
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
/* At least one descriptor must be left empty. */
|
||||
c = (chan->descs_num - chan->descs_used_count - 1);
|
||||
|
||||
*capacity = c;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
|
||||
struct xdma_sglist *sg, uint32_t sg_n)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_desc *desc;
|
||||
struct softdma_softc *sc;
|
||||
uint32_t enqueued;
|
||||
uint32_t saved_dir;
|
||||
uint32_t tmp;
|
||||
uint32_t len;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
enqueued = 0;
|
||||
|
||||
for (i = 0; i < sg_n; i++) {
|
||||
len = (uint32_t)sg[i].len;
|
||||
|
||||
desc = &chan->descs[chan->idx_head];
|
||||
desc->src_addr = sg[i].src_addr;
|
||||
desc->dst_addr = sg[i].dst_addr;
|
||||
if (sg[i].direction == XDMA_MEM_TO_DEV) {
|
||||
desc->src_incr = 1;
|
||||
desc->dst_incr = 0;
|
||||
} else {
|
||||
desc->src_incr = 0;
|
||||
desc->dst_incr = 1;
|
||||
}
|
||||
desc->direction = sg[i].direction;
|
||||
saved_dir = sg[i].direction;
|
||||
desc->len = len;
|
||||
desc->transfered = 0;
|
||||
desc->status = 0;
|
||||
desc->reserved = 0;
|
||||
desc->control = 0;
|
||||
|
||||
if (sg[i].first == 1)
|
||||
desc->control |= CONTROL_GEN_SOP;
|
||||
if (sg[i].last == 1)
|
||||
desc->control |= CONTROL_GEN_EOP;
|
||||
|
||||
tmp = chan->idx_head;
|
||||
chan->idx_head = softdma_next_desc(chan, chan->idx_head);
|
||||
atomic_add_int(&chan->descs_used_count, 1);
|
||||
desc->control |= CONTROL_OWN;
|
||||
enqueued += 1;
|
||||
}
|
||||
|
||||
if (enqueued == 0)
|
||||
return (0);
|
||||
|
||||
if (saved_dir == XDMA_MEM_TO_DEV) {
|
||||
chan->run = 1;
|
||||
wakeup(chan);
|
||||
} else
|
||||
softdma_memc_write(sc,
|
||||
A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,
|
||||
SOFTDMA_RX_EVENTS);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_request(device_t dev, struct xdma_channel *xchan,
|
||||
struct xdma_request *req)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_desc *desc;
|
||||
struct softdma_softc *sc;
|
||||
int ret;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
ret = softdma_desc_alloc(xchan);
|
||||
if (ret != 0) {
|
||||
device_printf(sc->dev,
|
||||
"%s: Can't allocate descriptors.\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
desc = &chan->descs[0];
|
||||
|
||||
desc->src_addr = req->src_addr;
|
||||
desc->dst_addr = req->dst_addr;
|
||||
desc->len = req->block_len;
|
||||
desc->src_incr = 1;
|
||||
desc->dst_incr = 1;
|
||||
desc->next = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd)
|
||||
{
|
||||
struct softdma_channel *chan;
|
||||
struct softdma_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
chan = (struct softdma_channel *)xchan->chan;
|
||||
|
||||
switch (cmd) {
|
||||
case XDMA_CMD_BEGIN:
|
||||
case XDMA_CMD_TERMINATE:
|
||||
case XDMA_CMD_PAUSE:
|
||||
/* TODO: implement me */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef FDT
|
||||
static int
|
||||
softdma_ofw_md_data(device_t dev, pcell_t *cells,
|
||||
int ncells, void **ptr)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static device_method_t softdma_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, softdma_probe),
|
||||
DEVMETHOD(device_attach, softdma_attach),
|
||||
DEVMETHOD(device_detach, softdma_detach),
|
||||
|
||||
/* xDMA Interface */
|
||||
DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc),
|
||||
DEVMETHOD(xdma_channel_free, softdma_channel_free),
|
||||
DEVMETHOD(xdma_channel_request, softdma_channel_request),
|
||||
DEVMETHOD(xdma_channel_control, softdma_channel_control),
|
||||
|
||||
/* xDMA SG Interface */
|
||||
DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg),
|
||||
DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg),
|
||||
DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity),
|
||||
|
||||
#ifdef FDT
|
||||
DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data),
|
||||
#endif
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t softdma_driver = {
|
||||
"softdma",
|
||||
softdma_methods,
|
||||
sizeof(struct softdma_softc),
|
||||
};
|
||||
|
||||
EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, 0, 0,
|
||||
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI memory interface.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
struct beri_mem_softc {
|
||||
struct resource *res[1];
|
||||
struct cdev *mem_cdev;
|
||||
device_t dev;
|
||||
int mem_size;
|
||||
int mem_start;
|
||||
};
|
||||
|
||||
static struct resource_spec beri_mem_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
mem_open(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct beri_mem_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mem_close(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct beri_mem_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mem_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mem_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot,
|
||||
vm_memattr_t *memattr)
|
||||
{
|
||||
struct beri_mem_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
if (offset < sc->mem_size) {
|
||||
*paddr = sc->mem_start + offset;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static struct cdevsw mem_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = mem_open,
|
||||
.d_close = mem_close,
|
||||
.d_ioctl = mem_ioctl,
|
||||
.d_mmap = mem_mmap,
|
||||
.d_name = "BERI memory",
|
||||
};
|
||||
|
||||
static int
|
||||
beri_mem_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-mem"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "BERI memory");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_mem_attach(device_t dev)
|
||||
{
|
||||
struct beri_mem_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, beri_mem_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory info */
|
||||
sc->mem_size = rman_get_size(sc->res[0]);
|
||||
sc->mem_start = rman_get_start(sc->res[0]);
|
||||
|
||||
sc->mem_cdev = make_dev(&mem_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
0600, "beri_mem");
|
||||
|
||||
if (sc->mem_cdev == NULL) {
|
||||
device_printf(dev, "Failed to create character device.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->mem_cdev->si_drv1 = sc;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t beri_mem_methods[] = {
|
||||
DEVMETHOD(device_probe, beri_mem_probe),
|
||||
DEVMETHOD(device_attach, beri_mem_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t beri_mem_driver = {
|
||||
"beri_mem",
|
||||
beri_mem_methods,
|
||||
sizeof(struct beri_mem_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(beri_mem, simplebus, beri_mem_driver, 0, 0);
|
||||
|
|
@ -1,524 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SRI-Cambridge BERI soft processor <-> ARM core ring buffer.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/selinfo.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_read_4((_sc)->res[0], _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_write_4((_sc)->res[0], _reg, _val)
|
||||
|
||||
#define CDES_INT_EN (1 << 15)
|
||||
#define CDES_CAUSE_MASK 0x3
|
||||
#define CDES_CAUSE_SHIFT 13
|
||||
#define DEVNAME_MAXLEN 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t cdes;
|
||||
uint16_t interrupt_level;
|
||||
uint16_t in;
|
||||
uint16_t out;
|
||||
} control_reg_t;
|
||||
|
||||
struct beri_softc {
|
||||
struct resource *res[3];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
struct cdev *cdev;
|
||||
device_t dev;
|
||||
void *read_ih;
|
||||
void *write_ih;
|
||||
struct selinfo beri_rsel;
|
||||
struct mtx beri_mtx;
|
||||
int opened;
|
||||
|
||||
char devname[DEVNAME_MAXLEN];
|
||||
int control_read;
|
||||
int control_write;
|
||||
int data_read;
|
||||
int data_write;
|
||||
int data_size;
|
||||
};
|
||||
|
||||
static struct resource_spec beri_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 1, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static control_reg_t
|
||||
get_control_reg(struct beri_softc *sc, int dir)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint16_t dst[4];
|
||||
control_reg_t c;
|
||||
uint16_t *cp;
|
||||
int i;
|
||||
|
||||
cp = (uint16_t *)&c;
|
||||
|
||||
offset = dir ? sc->control_write : sc->control_read;
|
||||
((uint32_t *)dst)[0] = READ4(sc, offset);
|
||||
((uint32_t *)dst)[1] = READ4(sc, offset + 4);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
cp[i] = dst[3 - i];
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
static void
|
||||
set_control_reg(struct beri_softc *sc, int dir, control_reg_t *c)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint16_t src[4];
|
||||
uint16_t *cp;
|
||||
int i;
|
||||
|
||||
cp = (uint16_t *)c;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
src[3 - i] = cp[i];
|
||||
|
||||
offset = dir ? sc->control_write : sc->control_read;
|
||||
WRITE4(sc, offset + 0, ((uint32_t *)src)[0]);
|
||||
WRITE4(sc, offset + 4, ((uint32_t *)src)[1]);
|
||||
}
|
||||
|
||||
static int
|
||||
get_stock(struct beri_softc *sc, int dir, control_reg_t *c)
|
||||
{
|
||||
uint32_t fill;
|
||||
|
||||
fill = (c->in - c->out + sc->data_size) % sc->data_size;
|
||||
|
||||
if (dir)
|
||||
return (sc->data_size - fill - 1);
|
||||
else
|
||||
return (fill);
|
||||
}
|
||||
|
||||
static void
|
||||
beri_intr_write(void *arg)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
control_reg_t c;
|
||||
|
||||
sc = arg;
|
||||
|
||||
c = get_control_reg(sc, 1);
|
||||
if (c.cdes & CDES_INT_EN) {
|
||||
c.cdes &= ~(CDES_INT_EN);
|
||||
set_control_reg(sc, 1, &c);
|
||||
}
|
||||
|
||||
mtx_lock(&sc->beri_mtx);
|
||||
selwakeuppri(&sc->beri_rsel, PZERO + 1);
|
||||
KNOTE_LOCKED(&sc->beri_rsel.si_note, 0);
|
||||
mtx_unlock(&sc->beri_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
beri_intr_read(void *arg)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
control_reg_t c;
|
||||
|
||||
sc = arg;
|
||||
|
||||
c = get_control_reg(sc, 0);
|
||||
if (c.cdes & CDES_INT_EN) {
|
||||
c.cdes &= ~(CDES_INT_EN);
|
||||
set_control_reg(sc, 0, &c);
|
||||
}
|
||||
|
||||
mtx_lock(&sc->beri_mtx);
|
||||
selwakeuppri(&sc->beri_rsel, PZERO + 1);
|
||||
KNOTE_LOCKED(&sc->beri_rsel.si_note, 0);
|
||||
mtx_unlock(&sc->beri_mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_open(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
control_reg_t c;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
if (sc->opened)
|
||||
return (1);
|
||||
|
||||
/* Setup interrupt handlers */
|
||||
if (bus_setup_intr(sc->dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, beri_intr_read, sc, &sc->read_ih)) {
|
||||
device_printf(sc->dev, "Unable to setup read intr\n");
|
||||
return (1);
|
||||
}
|
||||
if (bus_setup_intr(sc->dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, beri_intr_write, sc, &sc->write_ih)) {
|
||||
device_printf(sc->dev, "Unable to setup write intr\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
sc->opened = 1;
|
||||
|
||||
/* Clear write buffer */
|
||||
c = get_control_reg(sc, 1);
|
||||
c.in = c.out;
|
||||
c.cdes = 0;
|
||||
set_control_reg(sc, 1, &c);
|
||||
|
||||
/* Clear read buffer */
|
||||
c = get_control_reg(sc, 0);
|
||||
c.out = c.in;
|
||||
c.cdes = 0;
|
||||
set_control_reg(sc, 0, &c);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_close(struct cdev *dev, int flags __unused,
|
||||
int fmt __unused, struct thread *td __unused)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
if (sc->opened) {
|
||||
sc->opened = 0;
|
||||
|
||||
/* Unsetup interrupt handlers */
|
||||
bus_teardown_intr(sc->dev, sc->res[1], sc->read_ih);
|
||||
bus_teardown_intr(sc->dev, sc->res[2], sc->write_ih);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
uint32_t offset;
|
||||
control_reg_t c;
|
||||
uint16_t *ptr;
|
||||
uint8_t *dst;
|
||||
int stock;
|
||||
int dir;
|
||||
int amount;
|
||||
int count;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
dir = uio->uio_rw ? 1 : 0;
|
||||
|
||||
c = get_control_reg(sc, dir);
|
||||
stock = get_stock(sc, dir, &c);
|
||||
if (stock < uio->uio_resid) {
|
||||
device_printf(sc->dev, "Err: no data/space available\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
amount = uio->uio_resid;
|
||||
ptr = dir ? &c.in : &c.out;
|
||||
count = (sc->data_size - *ptr);
|
||||
|
||||
offset = dir ? sc->data_write : sc->data_read;
|
||||
dst = (uint8_t *)(sc->bsh + offset);
|
||||
|
||||
if (amount <= count) {
|
||||
uiomove(dst + *ptr, amount, uio);
|
||||
} else {
|
||||
uiomove(dst + *ptr, count, uio);
|
||||
uiomove(dst, (amount - count), uio);
|
||||
}
|
||||
|
||||
*ptr = (*ptr + amount) % sc->data_size;
|
||||
set_control_reg(sc, dir, &c);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_kqread(struct knote *kn, long hint)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
control_reg_t c;
|
||||
int stock;
|
||||
|
||||
sc = kn->kn_hook;
|
||||
|
||||
c = get_control_reg(sc, 0);
|
||||
stock = get_stock(sc, 0, &c);
|
||||
if (stock) {
|
||||
kn->kn_data = stock;
|
||||
return (1);
|
||||
}
|
||||
|
||||
kn->kn_data = 0;
|
||||
|
||||
/* Wait at least one new byte in buffer */
|
||||
c.interrupt_level = 1;
|
||||
|
||||
/* Enable interrupts */
|
||||
c.cdes |= (CDES_INT_EN);
|
||||
set_control_reg(sc, 0, &c);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_kqwrite(struct knote *kn, long hint)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
control_reg_t c;
|
||||
int stock;
|
||||
|
||||
sc = kn->kn_hook;
|
||||
|
||||
c = get_control_reg(sc, 1);
|
||||
stock = get_stock(sc, 1, &c);
|
||||
if (stock) {
|
||||
kn->kn_data = stock;
|
||||
return (1);
|
||||
}
|
||||
|
||||
kn->kn_data = 0;
|
||||
|
||||
/* Wait at least one free position in buffer */
|
||||
c.interrupt_level = sc->data_size - 2;
|
||||
|
||||
/* Enable interrupts */
|
||||
c.cdes |= (CDES_INT_EN);
|
||||
set_control_reg(sc, 1, &c);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
beri_kqdetach(struct knote *kn)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
|
||||
sc = kn->kn_hook;
|
||||
|
||||
knlist_remove(&sc->beri_rsel.si_note, kn, 0);
|
||||
}
|
||||
|
||||
static const struct filterops beri_read_filterops = {
|
||||
.f_isfd = 1,
|
||||
.f_attach = NULL,
|
||||
.f_detach = beri_kqdetach,
|
||||
.f_event = beri_kqread,
|
||||
};
|
||||
|
||||
static const struct filterops beri_write_filterops = {
|
||||
.f_isfd = 1,
|
||||
.f_attach = NULL,
|
||||
.f_detach = beri_kqdetach,
|
||||
.f_event = beri_kqwrite,
|
||||
};
|
||||
|
||||
static int
|
||||
beri_kqfilter(struct cdev *dev, struct knote *kn)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
switch(kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
kn->kn_fop = &beri_read_filterops;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
kn->kn_fop = &beri_write_filterops;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
kn->kn_hook = sc;
|
||||
knlist_add(&sc->beri_rsel.si_note, kn, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cdevsw beri_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = beri_open,
|
||||
.d_close = beri_close,
|
||||
.d_write = beri_rdwr,
|
||||
.d_read = beri_rdwr,
|
||||
.d_kqfilter = beri_kqfilter,
|
||||
.d_name = "beri ring buffer",
|
||||
};
|
||||
|
||||
static int
|
||||
parse_fdt(struct beri_softc *sc)
|
||||
{
|
||||
pcell_t dts_value[0];
|
||||
phandle_t node;
|
||||
int len;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
/* get device name */
|
||||
if (OF_getprop(ofw_bus_get_node(sc->dev), "device_name",
|
||||
&sc->devname, sizeof(sc->devname)) <= 0) {
|
||||
device_printf(sc->dev, "Can't get device_name\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((len = OF_getproplen(node, "data_size")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "data_size", dts_value, len);
|
||||
sc->data_size = dts_value[0];
|
||||
|
||||
if ((len = OF_getproplen(node, "data_read")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "data_read", dts_value, len);
|
||||
sc->data_read = dts_value[0];
|
||||
|
||||
if ((len = OF_getproplen(node, "data_write")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "data_write", dts_value, len);
|
||||
sc->data_write = dts_value[0];
|
||||
|
||||
if ((len = OF_getproplen(node, "control_read")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "control_read", dts_value, len);
|
||||
sc->control_read = dts_value[0];
|
||||
|
||||
if ((len = OF_getproplen(node, "control_write")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(node, "control_write", dts_value, len);
|
||||
sc->control_write = dts_value[0];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-ring"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "SRI-Cambridge BERI ring buffer");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_attach(device_t dev)
|
||||
{
|
||||
struct beri_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, beri_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
if (parse_fdt(sc)) {
|
||||
device_printf(sc->dev, "Can't get FDT values\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
S_IRWXU, "%s", sc->devname);
|
||||
if (sc->cdev == NULL) {
|
||||
device_printf(dev, "Failed to create character device.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->cdev->si_drv1 = sc;
|
||||
|
||||
mtx_init(&sc->beri_mtx, "beri_mtx", NULL, MTX_DEF);
|
||||
knlist_init_mtx(&sc->beri_rsel.si_note, &sc->beri_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t beri_methods[] = {
|
||||
DEVMETHOD(device_probe, beri_probe),
|
||||
DEVMETHOD(device_attach, beri_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t beri_driver = {
|
||||
"beri_ring",
|
||||
beri_methods,
|
||||
sizeof(struct beri_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(beri_ring, simplebus, beri_driver, 0, 0);
|
||||
|
|
@ -1,648 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI Virtio Networking Frontend
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mdioctl.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio.h>
|
||||
#include <dev/beri/virtio/virtio_mmio_platform.h>
|
||||
|
||||
#include <dev/altera/pio/pio.h>
|
||||
|
||||
#include <dev/virtio/mmio/virtio_mmio.h>
|
||||
#include <dev/virtio/network/virtio_net.h>
|
||||
#include <dev/virtio/virtio_ids.h>
|
||||
#include <dev/virtio/virtio_config.h>
|
||||
#include <dev/virtio/virtio_ring.h>
|
||||
|
||||
#include "pio_if.h"
|
||||
|
||||
#define DPRINTF(fmt, args...) printf(fmt, ##args)
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_read_4((_sc)->res[0], _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_write_4((_sc)->res[0], _reg, _val)
|
||||
|
||||
#define VTBE_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define VTBE_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define VTBE_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
|
||||
#define VTBE_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
|
||||
|
||||
/*
|
||||
* Driver data and defines.
|
||||
*/
|
||||
#define DESC_COUNT 256
|
||||
|
||||
struct vtbe_softc {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
if_t ifp;
|
||||
int if_flags;
|
||||
struct mtx mtx;
|
||||
boolean_t is_attached;
|
||||
|
||||
int beri_mem_offset;
|
||||
device_t pio_send;
|
||||
device_t pio_recv;
|
||||
int opened;
|
||||
|
||||
struct vqueue_info vs_queues[2];
|
||||
int vs_curq;
|
||||
int hdrsize;
|
||||
};
|
||||
|
||||
static struct resource_spec vtbe_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static void vtbe_txfinish_locked(struct vtbe_softc *sc);
|
||||
static void vtbe_rxfinish_locked(struct vtbe_softc *sc);
|
||||
static void vtbe_stop_locked(struct vtbe_softc *sc);
|
||||
static int pio_enable_irq(struct vtbe_softc *sc, int enable);
|
||||
|
||||
static void
|
||||
vtbe_txstart_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct iovec iov[DESC_COUNT];
|
||||
struct virtio_net_hdr *vnh;
|
||||
struct vqueue_info *vq;
|
||||
struct iovec *tiov;
|
||||
if_t ifp;
|
||||
struct mbuf *m;
|
||||
struct uio uio;
|
||||
int enqueued;
|
||||
int iolen;
|
||||
int error;
|
||||
int reg;
|
||||
int len;
|
||||
int n;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
/* RX queue */
|
||||
vq = &sc->vs_queues[0];
|
||||
if (!vq_has_descs(vq)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = sc->ifp;
|
||||
if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
enqueued = 0;
|
||||
|
||||
if (!vq_ring_ready(vq))
|
||||
return;
|
||||
|
||||
vq->vq_save_used = be16toh(vq->vq_used->idx);
|
||||
|
||||
for (;;) {
|
||||
if (!vq_has_descs(vq)) {
|
||||
if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
m = if_dequeue(ifp);
|
||||
if (m == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = vq_getchain(sc->beri_mem_offset, vq, iov,
|
||||
DESC_COUNT, NULL);
|
||||
KASSERT(n == 2,
|
||||
("Unexpected amount of descriptors (%d)", n));
|
||||
|
||||
tiov = getcopy(iov, n);
|
||||
vnh = iov[0].iov_base;
|
||||
memset(vnh, 0, sc->hdrsize);
|
||||
|
||||
len = iov[1].iov_len;
|
||||
uio.uio_resid = len;
|
||||
uio.uio_iov = &tiov[1];
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_offset = 0;
|
||||
uio.uio_rw = UIO_READ;
|
||||
|
||||
error = m_mbuftouio(&uio, m, 0);
|
||||
if (error)
|
||||
panic("m_mbuftouio failed\n");
|
||||
|
||||
iolen = (len - uio.uio_resid + sc->hdrsize);
|
||||
|
||||
free(tiov, M_DEVBUF);
|
||||
vq_relchain(vq, iov, n, iolen);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
BPF_MTAP(ifp, m);
|
||||
m_freem(m);
|
||||
|
||||
++enqueued;
|
||||
}
|
||||
|
||||
if (enqueued != 0) {
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_txstart(if_t ifp)
|
||||
{
|
||||
struct vtbe_softc *sc = if_getsoftc(ifp);
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
vtbe_txstart_locked(sc);
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_stop_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
if_t ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
ifp = sc->ifp;
|
||||
if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE));
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_init_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
if_t ifp = sc->ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
|
||||
return;
|
||||
|
||||
if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_init(void *if_softc)
|
||||
{
|
||||
struct vtbe_softc *sc = if_softc;
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
vtbe_init_locked(sc);
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_ioctl(if_t ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ifmediareq *ifmr;
|
||||
struct vtbe_softc *sc;
|
||||
struct ifreq *ifr;
|
||||
int mask, error;
|
||||
|
||||
sc = if_getsoftc(ifp);
|
||||
ifr = (struct ifreq *)data;
|
||||
|
||||
error = 0;
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
VTBE_LOCK(sc);
|
||||
if (if_getflags(ifp) & IFF_UP) {
|
||||
pio_enable_irq(sc, 1);
|
||||
|
||||
if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) {
|
||||
vtbe_init_locked(sc);
|
||||
}
|
||||
} else {
|
||||
pio_enable_irq(sc, 0);
|
||||
|
||||
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
|
||||
vtbe_stop_locked(sc);
|
||||
}
|
||||
}
|
||||
sc->if_flags = if_getflags(ifp);
|
||||
VTBE_UNLOCK(sc);
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
break;
|
||||
case SIOCSIFMEDIA:
|
||||
case SIOCGIFMEDIA:
|
||||
ifmr = (struct ifmediareq *)data;
|
||||
ifmr->ifm_count = 1;
|
||||
ifmr->ifm_status = (IFM_AVALID | IFM_ACTIVE);
|
||||
ifmr->ifm_active = (IFM_ETHER | IFM_10G_T | IFM_FDX);
|
||||
ifmr->ifm_current = ifmr->ifm_active;
|
||||
break;
|
||||
case SIOCSIFCAP:
|
||||
mask = if_getcapenable(ifp) ^ ifr->ifr_reqcap;
|
||||
if (mask & IFCAP_VLAN_MTU) {
|
||||
if_togglecapenable(ifp, IFCAP_VLAN_MTU);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR:
|
||||
pio_enable_irq(sc, 1);
|
||||
default:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_txfinish_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
if_t ifp;
|
||||
|
||||
VTBE_ASSERT_LOCKED(sc);
|
||||
|
||||
ifp = sc->ifp;
|
||||
}
|
||||
|
||||
static int
|
||||
vq_init(struct vtbe_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
uint8_t *base;
|
||||
int size;
|
||||
int reg;
|
||||
int pfn;
|
||||
|
||||
vq = &sc->vs_queues[sc->vs_curq];
|
||||
vq->vq_qsize = DESC_COUNT;
|
||||
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
|
||||
pfn = be32toh(reg);
|
||||
vq->vq_pfn = pfn;
|
||||
|
||||
size = vring_size(vq->vq_qsize, VRING_ALIGN);
|
||||
base = paddr_map(sc->beri_mem_offset,
|
||||
(pfn << PAGE_SHIFT), size);
|
||||
|
||||
/* First pages are descriptors */
|
||||
vq->vq_desc = (struct vring_desc *)base;
|
||||
base += vq->vq_qsize * sizeof(struct vring_desc);
|
||||
|
||||
/* Then avail ring */
|
||||
vq->vq_avail = (struct vring_avail *)base;
|
||||
base += (2 + vq->vq_qsize + 1) * sizeof(uint16_t);
|
||||
|
||||
/* Then it's rounded up to the next page */
|
||||
base = (uint8_t *)roundup2((uintptr_t)base, VRING_ALIGN);
|
||||
|
||||
/* And the last pages are the used ring */
|
||||
vq->vq_used = (struct vring_used *)base;
|
||||
|
||||
/* Mark queue as allocated, and start at 0 when we use it. */
|
||||
vq->vq_flags = VQ_ALLOC;
|
||||
vq->vq_last_avail = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
|
||||
{
|
||||
struct iovec iov[DESC_COUNT];
|
||||
struct iovec *tiov;
|
||||
if_t ifp;
|
||||
struct uio uio;
|
||||
struct mbuf *m;
|
||||
int iolen;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
ifp = sc->ifp;
|
||||
|
||||
n = vq_getchain(sc->beri_mem_offset, vq, iov,
|
||||
DESC_COUNT, NULL);
|
||||
|
||||
KASSERT(n >= 1 && n <= DESC_COUNT,
|
||||
("wrong n %d", n));
|
||||
|
||||
tiov = getcopy(iov, n);
|
||||
|
||||
iolen = 0;
|
||||
for (i = 1; i < n; i++) {
|
||||
iolen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
uio.uio_resid = iolen;
|
||||
uio.uio_iov = &tiov[1];
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_iovcnt = (n - 1);
|
||||
uio.uio_rw = UIO_WRITE;
|
||||
|
||||
if ((m = m_uiotombuf(&uio, M_NOWAIT, 0, ETHER_ALIGN,
|
||||
M_PKTHDR)) == NULL) {
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
|
||||
CURVNET_SET(if_getvnet(ifp));
|
||||
VTBE_UNLOCK(sc);
|
||||
if_input(ifp, m);
|
||||
VTBE_LOCK(sc);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
done:
|
||||
free(tiov, M_DEVBUF);
|
||||
vq_relchain(vq, iov, n, iolen + sc->hdrsize);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_rxfinish_locked(struct vtbe_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
int reg;
|
||||
|
||||
/* TX queue */
|
||||
vq = &sc->vs_queues[1];
|
||||
if (!vq_ring_ready(vq))
|
||||
return;
|
||||
|
||||
/* Process new descriptors */
|
||||
vq->vq_save_used = be16toh(vq->vq_used->idx);
|
||||
|
||||
while (vq_has_descs(vq)) {
|
||||
vtbe_proc_rx(sc, vq);
|
||||
}
|
||||
|
||||
/* Interrupt the other side */
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
vtbe_intr(void *arg)
|
||||
{
|
||||
struct vtbe_softc *sc;
|
||||
int pending;
|
||||
uint32_t reg;
|
||||
|
||||
sc = arg;
|
||||
|
||||
VTBE_LOCK(sc);
|
||||
|
||||
reg = PIO_READ(sc->pio_recv);
|
||||
|
||||
/* Ack */
|
||||
PIO_SET(sc->pio_recv, reg, 0);
|
||||
|
||||
pending = htobe32(reg);
|
||||
if (pending & Q_SEL) {
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_SEL);
|
||||
sc->vs_curq = be32toh(reg);
|
||||
}
|
||||
|
||||
if (pending & Q_PFN) {
|
||||
vq_init(sc);
|
||||
}
|
||||
|
||||
if (pending & Q_NOTIFY) {
|
||||
/* beri rx / arm tx notify */
|
||||
vtbe_txfinish_locked(sc);
|
||||
}
|
||||
|
||||
if (pending & Q_NOTIFY1) {
|
||||
vtbe_rxfinish_locked(sc);
|
||||
}
|
||||
|
||||
VTBE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_get_hwaddr(struct vtbe_softc *sc, uint8_t *hwaddr)
|
||||
{
|
||||
int rnd;
|
||||
|
||||
/*
|
||||
* Generate MAC address, use 'bsd' + random 24 low-order bits.
|
||||
*/
|
||||
|
||||
rnd = arc4random() & 0x00ffffff;
|
||||
|
||||
hwaddr[0] = 'b';
|
||||
hwaddr[1] = 's';
|
||||
hwaddr[2] = 'd';
|
||||
hwaddr[3] = rnd >> 16;
|
||||
hwaddr[4] = rnd >> 8;
|
||||
hwaddr[5] = rnd >> 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pio_enable_irq(struct vtbe_softc *sc, int enable)
|
||||
{
|
||||
|
||||
/*
|
||||
* IRQ lines should be disabled while reprogram FPGA core.
|
||||
*/
|
||||
|
||||
if (enable) {
|
||||
if (sc->opened == 0) {
|
||||
sc->opened = 1;
|
||||
PIO_SETUP_IRQ(sc->pio_recv, vtbe_intr, sc);
|
||||
}
|
||||
} else {
|
||||
if (sc->opened == 1) {
|
||||
PIO_TEARDOWN_IRQ(sc->pio_recv);
|
||||
sc->opened = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-vtnet"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Virtio BERI Ethernet Controller");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
vtbe_attach(device_t dev)
|
||||
{
|
||||
uint8_t macaddr[ETHER_ADDR_LEN];
|
||||
struct vtbe_softc *sc;
|
||||
if_t ifp;
|
||||
int reg;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
sc->hdrsize = sizeof(struct virtio_net_hdr);
|
||||
|
||||
if (bus_alloc_resources(dev, vtbe_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
|
||||
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* Setup MMIO */
|
||||
|
||||
/* Specify that we provide network device */
|
||||
reg = htobe32(VIRTIO_ID_NETWORK);
|
||||
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
|
||||
|
||||
/* The number of desc we support */
|
||||
reg = htobe32(DESC_COUNT);
|
||||
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
|
||||
|
||||
/* Our features */
|
||||
reg = htobe32(VIRTIO_NET_F_MAC |
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg);
|
||||
|
||||
/* Get MAC */
|
||||
if (vtbe_get_hwaddr(sc, macaddr)) {
|
||||
device_printf(sc->dev, "can't get mac\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Set up the ethernet interface. */
|
||||
sc->ifp = ifp = if_alloc(IFT_ETHER);
|
||||
if_setbaudrate(ifp, IF_Gbps(10));
|
||||
if_setsoftc(ifp, sc);
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX |
|
||||
IFF_MULTICAST | IFF_PROMISC);
|
||||
if_setcapabilities(ifp, IFCAP_VLAN_MTU);
|
||||
if_setcapenable(ifp, if_getcapabilities(ifp));
|
||||
if_setstartfn(ifp, vtbe_txstart);
|
||||
if_setioctlfn(ifp, vtbe_ioctl);
|
||||
if_setinitfn(ifp, vtbe_init);
|
||||
if_setsendqlen(ifp, DESC_COUNT - 1);
|
||||
if_setsendqready(ifp);
|
||||
if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
|
||||
|
||||
/* All ready to run, attach the ethernet interface. */
|
||||
ether_ifattach(ifp, macaddr);
|
||||
|
||||
sc->is_attached = true;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t vtbe_methods[] = {
|
||||
DEVMETHOD(device_probe, vtbe_probe),
|
||||
DEVMETHOD(device_attach, vtbe_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t vtbe_driver = {
|
||||
"vtbe",
|
||||
vtbe_methods,
|
||||
sizeof(struct vtbe_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(vtbe, simplebus, vtbe_driver, 0, 0);
|
||||
MODULE_DEPEND(vtbe, ether, 1, 1, 1);
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI virtio mmio backend common methods
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio.h>
|
||||
#include <dev/virtio/virtqueue.h>
|
||||
#include <dev/virtio/virtio_ring.h>
|
||||
#include <dev/altera/pio/pio.h>
|
||||
|
||||
#include "pio_if.h"
|
||||
|
||||
int
|
||||
vq_ring_ready(struct vqueue_info *vq)
|
||||
{
|
||||
|
||||
return (vq->vq_flags & VQ_ALLOC);
|
||||
}
|
||||
|
||||
int
|
||||
vq_has_descs(struct vqueue_info *vq)
|
||||
{
|
||||
|
||||
return (vq_ring_ready(vq) && vq->vq_last_avail !=
|
||||
be16toh(vq->vq_avail->idx));
|
||||
}
|
||||
|
||||
void *
|
||||
paddr_map(uint32_t offset, uint32_t phys, uint32_t size)
|
||||
{
|
||||
bus_space_handle_t bsh;
|
||||
|
||||
if (bus_space_map(fdtbus_bs_tag, (phys + offset),
|
||||
size, 0, &bsh) != 0) {
|
||||
panic("Couldn't map 0x%08x\n", (phys + offset));
|
||||
}
|
||||
|
||||
return (void *)(bsh);
|
||||
}
|
||||
|
||||
void
|
||||
paddr_unmap(void *phys, uint32_t size)
|
||||
{
|
||||
|
||||
bus_space_unmap(fdtbus_bs_tag, (bus_space_handle_t)phys, size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_vq_record(uint32_t offs, int i, volatile struct vring_desc *vd,
|
||||
struct iovec *iov, int n_iov, uint16_t *flags) {
|
||||
uint32_t len;
|
||||
uint64_t addr;
|
||||
|
||||
if (i >= n_iov)
|
||||
return;
|
||||
|
||||
len = atomic_load_32(&vd->len);
|
||||
addr = atomic_load_64(&vd->addr);
|
||||
iov[i].iov_base = paddr_map(offs, be64toh(addr),
|
||||
be32toh(len));
|
||||
iov[i].iov_len = be32toh(len);
|
||||
if (flags != NULL)
|
||||
flags[i] = be16toh(vd->flags);
|
||||
}
|
||||
|
||||
int
|
||||
vq_getchain(uint32_t offs, struct vqueue_info *vq,
|
||||
struct iovec *iov, int n_iov, uint16_t *flags)
|
||||
{
|
||||
volatile struct vring_desc *vdir, *vindir, *vp;
|
||||
int idx, ndesc, n_indir;
|
||||
int head, next;
|
||||
int i;
|
||||
|
||||
idx = vq->vq_last_avail;
|
||||
ndesc = (be16toh(vq->vq_avail->idx) - idx);
|
||||
if (ndesc == 0)
|
||||
return (0);
|
||||
|
||||
head = be16toh(vq->vq_avail->ring[idx & (vq->vq_qsize - 1)]);
|
||||
next = head;
|
||||
|
||||
for (i = 0; i < VQ_MAX_DESCRIPTORS; next = be16toh(vdir->next)) {
|
||||
vdir = &vq->vq_desc[next];
|
||||
if ((be16toh(vdir->flags) & VRING_DESC_F_INDIRECT) == 0) {
|
||||
_vq_record(offs, i, vdir, iov, n_iov, flags);
|
||||
i++;
|
||||
} else {
|
||||
n_indir = be32toh(vdir->len) / 16;
|
||||
vindir = paddr_map(offs, be64toh(vdir->addr),
|
||||
be32toh(vdir->len));
|
||||
next = 0;
|
||||
for (;;) {
|
||||
vp = &vindir[next];
|
||||
_vq_record(offs, i, vp, iov, n_iov, flags);
|
||||
i+=1;
|
||||
if ((be16toh(vp->flags) & \
|
||||
VRING_DESC_F_NEXT) == 0)
|
||||
break;
|
||||
next = be16toh(vp->next);
|
||||
}
|
||||
paddr_unmap(__DEVOLATILE(void *, vindir), be32toh(vdir->len));
|
||||
}
|
||||
|
||||
if ((be16toh(vdir->flags) & VRING_DESC_F_NEXT) == 0)
|
||||
return (i);
|
||||
}
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
void
|
||||
vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
|
||||
{
|
||||
volatile struct vring_used_elem *vue;
|
||||
volatile struct vring_used *vu;
|
||||
uint16_t head, uidx, mask;
|
||||
int i;
|
||||
|
||||
mask = vq->vq_qsize - 1;
|
||||
vu = vq->vq_used;
|
||||
head = be16toh(vq->vq_avail->ring[vq->vq_last_avail++ & mask]);
|
||||
|
||||
uidx = be16toh(vu->idx);
|
||||
vue = &vu->ring[uidx++ & mask];
|
||||
vue->id = htobe32(head);
|
||||
|
||||
vue->len = htobe32(iolen);
|
||||
vu->idx = htobe16(uidx);
|
||||
|
||||
/* Clean up */
|
||||
for (i = 0; i < n; i++) {
|
||||
paddr_unmap((void *)iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
setup_pio(device_t dev, char *name, device_t *pio_dev)
|
||||
{
|
||||
phandle_t pio_node;
|
||||
struct fdt_ic *ic;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
|
||||
if ((node = ofw_bus_get_node(dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, name, &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pio_node = OF_node_from_xref(xref);
|
||||
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
|
||||
if (ic->iph == pio_node) {
|
||||
*pio_dev = ic->dev;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
setup_offset(device_t dev, uint32_t *offset)
|
||||
{
|
||||
pcell_t dts_value[2];
|
||||
phandle_t mem_node;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
int len;
|
||||
|
||||
if ((node = ofw_bus_get_node(dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, "beri-mem", &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mem_node = OF_node_from_xref(xref);
|
||||
if ((len = OF_getproplen(mem_node, "reg")) <= 0)
|
||||
return (ENXIO);
|
||||
OF_getencprop(mem_node, "reg", dts_value, len);
|
||||
*offset = dts_value[0];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct iovec *
|
||||
getcopy(struct iovec *iov, int n)
|
||||
{
|
||||
struct iovec *tiov;
|
||||
int i;
|
||||
|
||||
tiov = malloc(n * sizeof(struct iovec), M_DEVBUF, M_NOWAIT);
|
||||
for (i = 0; i < n; i++) {
|
||||
tiov[i].iov_base = iov[i].iov_base;
|
||||
tiov[i].iov_len = iov[i].iov_len;
|
||||
}
|
||||
|
||||
return (tiov);
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define READ2(_sc, _reg) \
|
||||
bus_read_2((_sc)->res[0], _reg)
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_read_4((_sc)->res[0], _reg)
|
||||
#define WRITE2(_sc, _reg, _val) \
|
||||
bus_write_2((_sc)->res[0], _reg, _val)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_write_4((_sc)->res[0], _reg, _val)
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
#define VRING_ALIGN 4096
|
||||
|
||||
#define VQ_ALLOC 0x01 /* set once we have a pfn */
|
||||
#define VQ_MAX_DESCRIPTORS 512
|
||||
|
||||
struct vqueue_info {
|
||||
uint16_t vq_qsize; /* size of this queue (a power of 2) */
|
||||
uint16_t vq_num;
|
||||
uint16_t vq_flags;
|
||||
uint16_t vq_last_avail; /* a recent value of vq_avail->va_idx */
|
||||
uint16_t vq_save_used; /* saved vq_used->vu_idx; see vq_endchains */
|
||||
uint32_t vq_pfn; /* PFN of virt queue (not shifted!) */
|
||||
|
||||
volatile struct vring_desc *vq_desc; /* descriptor array */
|
||||
volatile struct vring_avail *vq_avail; /* the "avail" ring */
|
||||
volatile struct vring_used *vq_used; /* the "used" ring */
|
||||
};
|
||||
|
||||
int vq_ring_ready(struct vqueue_info *vq);
|
||||
int vq_has_descs(struct vqueue_info *vq);
|
||||
void * paddr_map(uint32_t offset, uint32_t phys, uint32_t size);
|
||||
void paddr_unmap(void *phys, uint32_t size);
|
||||
int vq_getchain(uint32_t beri_mem_offset, struct vqueue_info *vq,
|
||||
struct iovec *iov, int n_iov, uint16_t *flags);
|
||||
void vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen);
|
||||
struct iovec * getcopy(struct iovec *iov, int n);
|
||||
|
||||
int setup_pio(device_t dev, char *name, device_t *pio_dev);
|
||||
int setup_offset(device_t dev, uint32_t *offset);
|
||||
|
|
@ -1,553 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI virtio block backend driver
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/mdioctl.h>
|
||||
#include <sys/namei.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio.h>
|
||||
#include <dev/beri/virtio/virtio_mmio_platform.h>
|
||||
#include <dev/altera/pio/pio.h>
|
||||
#include <dev/virtio/mmio/virtio_mmio.h>
|
||||
#include <dev/virtio/block/virtio_blk.h>
|
||||
#include <dev/virtio/virtio_ids.h>
|
||||
#include <dev/virtio/virtio_config.h>
|
||||
#include <dev/virtio/virtio_ring.h>
|
||||
|
||||
#include "pio_if.h"
|
||||
|
||||
#define DPRINTF(fmt, ...)
|
||||
|
||||
/* We use indirect descriptors */
|
||||
#define NUM_DESCS 1
|
||||
#define NUM_QUEUES 1
|
||||
|
||||
#define VTBLK_BLK_ID_BYTES 20
|
||||
#define VTBLK_MAXSEGS 256
|
||||
|
||||
struct beri_vtblk_softc {
|
||||
struct resource *res[1];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
struct cdev *cdev;
|
||||
device_t dev;
|
||||
int opened;
|
||||
device_t pio_recv;
|
||||
device_t pio_send;
|
||||
struct vqueue_info vs_queues[NUM_QUEUES];
|
||||
char ident[VTBLK_BLK_ID_BYTES];
|
||||
struct ucred *cred;
|
||||
struct vnode *vnode;
|
||||
struct thread *vtblk_ktd;
|
||||
struct sx sc_mtx;
|
||||
int beri_mem_offset;
|
||||
struct md_ioctl *mdio;
|
||||
struct virtio_blk_config *cfg;
|
||||
};
|
||||
|
||||
static struct resource_spec beri_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
vtblk_rdwr(struct beri_vtblk_softc *sc, struct iovec *iov,
|
||||
int cnt, int offset, int operation, int iolen)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct mount *mp;
|
||||
struct uio auio;
|
||||
int error;
|
||||
|
||||
bzero(&auio, sizeof(auio));
|
||||
|
||||
vp = sc->vnode;
|
||||
|
||||
KASSERT(vp != NULL, ("file not opened"));
|
||||
|
||||
auio.uio_iov = iov;
|
||||
auio.uio_iovcnt = cnt;
|
||||
auio.uio_offset = offset;
|
||||
auio.uio_segflg = UIO_SYSSPACE;
|
||||
auio.uio_rw = operation;
|
||||
auio.uio_resid = iolen;
|
||||
auio.uio_td = curthread;
|
||||
|
||||
if (operation == 0) {
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
error = VOP_READ(vp, &auio, IO_DIRECT, sc->cred);
|
||||
VOP_UNLOCK(vp);
|
||||
} else {
|
||||
(void) vn_start_write(vp, &mp, V_WAIT);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
error = VOP_WRITE(vp, &auio, IO_SYNC, sc->cred);
|
||||
VOP_UNLOCK(vp);
|
||||
vn_finished_write(mp);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq)
|
||||
{
|
||||
struct iovec iov[VTBLK_MAXSEGS + 2];
|
||||
uint16_t flags[VTBLK_MAXSEGS + 2];
|
||||
struct virtio_blk_outhdr *vbh;
|
||||
struct iovec *tiov;
|
||||
uint8_t *status;
|
||||
off_t offset;
|
||||
int iolen;
|
||||
int type;
|
||||
int i, n;
|
||||
int err;
|
||||
|
||||
n = vq_getchain(sc->beri_mem_offset, vq, iov,
|
||||
VTBLK_MAXSEGS + 2, flags);
|
||||
KASSERT(n >= 2 && n <= VTBLK_MAXSEGS + 2,
|
||||
("wrong n value %d", n));
|
||||
|
||||
tiov = getcopy(iov, n);
|
||||
vbh = iov[0].iov_base;
|
||||
|
||||
status = iov[n-1].iov_base;
|
||||
KASSERT(iov[n-1].iov_len == 1,
|
||||
("iov_len == %d", iov[n-1].iov_len));
|
||||
|
||||
type = be32toh(vbh->type) & ~VIRTIO_BLK_T_BARRIER;
|
||||
offset = be64toh(vbh->sector) * DEV_BSIZE;
|
||||
|
||||
iolen = 0;
|
||||
for (i = 1; i < (n-1); i++) {
|
||||
iolen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VIRTIO_BLK_T_OUT:
|
||||
case VIRTIO_BLK_T_IN:
|
||||
err = vtblk_rdwr(sc, tiov + 1, i - 1,
|
||||
offset, type, iolen);
|
||||
break;
|
||||
case VIRTIO_BLK_T_GET_ID:
|
||||
/* Assume a single buffer */
|
||||
strncpy(iov[1].iov_base, sc->ident,
|
||||
MIN(iov[1].iov_len, sizeof(sc->ident)));
|
||||
err = 0;
|
||||
break;
|
||||
case VIRTIO_BLK_T_FLUSH:
|
||||
/* Possible? */
|
||||
default:
|
||||
err = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
if (err == -ENOSYS) {
|
||||
*status = VIRTIO_BLK_S_UNSUPP;
|
||||
} else
|
||||
*status = VIRTIO_BLK_S_IOERR;
|
||||
} else
|
||||
*status = VIRTIO_BLK_S_OK;
|
||||
|
||||
free(tiov, M_DEVBUF);
|
||||
vq_relchain(vq, iov, n, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
close_file(struct beri_vtblk_softc *sc, struct thread *td)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (sc->vnode != NULL) {
|
||||
vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY);
|
||||
sc->vnode->v_vflag &= ~VV_MD;
|
||||
VOP_UNLOCK(sc->vnode);
|
||||
error = vn_close(sc->vnode, (FREAD|FWRITE),
|
||||
sc->cred, td);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
sc->vnode = NULL;
|
||||
}
|
||||
|
||||
if (sc->cred != NULL)
|
||||
crfree(sc->cred);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
open_file(struct beri_vtblk_softc *sc, struct thread *td)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct vattr vattr;
|
||||
int error;
|
||||
int flags;
|
||||
|
||||
flags = (FREAD | FWRITE);
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->mdio->md_file);
|
||||
error = vn_open(&nd, &flags, 0, NULL);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
NDFREE_PNBUF(&nd);
|
||||
|
||||
if (nd.ni_vp->v_type != VREG) {
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) {
|
||||
vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY);
|
||||
if (VN_IS_DOOMED(nd.ni_vp)) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
nd.ni_vp->v_vflag |= VV_MD;
|
||||
VOP_UNLOCK(nd.ni_vp);
|
||||
|
||||
sc->vnode = nd.ni_vp;
|
||||
sc->cred = crhold(td->td_ucred);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vtblk_notify(struct beri_vtblk_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
int queue;
|
||||
int reg;
|
||||
|
||||
vq = &sc->vs_queues[0];
|
||||
if (!vq_ring_ready(vq))
|
||||
return (0);
|
||||
|
||||
if (!sc->opened)
|
||||
return (0);
|
||||
|
||||
reg = READ2(sc, VIRTIO_MMIO_QUEUE_NOTIFY);
|
||||
queue = be16toh(reg);
|
||||
|
||||
KASSERT(queue == 0, ("we support single queue only"));
|
||||
|
||||
/* Process new descriptors */
|
||||
vq = &sc->vs_queues[queue];
|
||||
vq->vq_save_used = be16toh(vq->vq_used->idx);
|
||||
while (vq_has_descs(vq))
|
||||
vtblk_proc(sc, vq);
|
||||
|
||||
/* Interrupt the other side */
|
||||
if ((be16toh(vq->vq_avail->flags) & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
|
||||
reg = htobe32(VIRTIO_MMIO_INT_VRING);
|
||||
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
|
||||
PIO_SET(sc->pio_send, Q_INTR, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vq_init(struct beri_vtblk_softc *sc)
|
||||
{
|
||||
struct vqueue_info *vq;
|
||||
uint8_t *base;
|
||||
int size;
|
||||
int reg;
|
||||
int pfn;
|
||||
|
||||
vq = &sc->vs_queues[0];
|
||||
vq->vq_qsize = NUM_DESCS;
|
||||
|
||||
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
|
||||
pfn = be32toh(reg);
|
||||
vq->vq_pfn = pfn;
|
||||
|
||||
size = vring_size(vq->vq_qsize, VRING_ALIGN);
|
||||
base = paddr_map(sc->beri_mem_offset,
|
||||
(pfn << PAGE_SHIFT), size);
|
||||
|
||||
/* First pages are descriptors */
|
||||
vq->vq_desc = (struct vring_desc *)base;
|
||||
base += vq->vq_qsize * sizeof(struct vring_desc);
|
||||
|
||||
/* Then avail ring */
|
||||
vq->vq_avail = (struct vring_avail *)base;
|
||||
base += (2 + vq->vq_qsize + 1) * sizeof(uint16_t);
|
||||
|
||||
/* Then it's rounded up to the next page */
|
||||
base = (uint8_t *)roundup2((uintptr_t)base, VRING_ALIGN);
|
||||
|
||||
/* And the last pages are the used ring */
|
||||
vq->vq_used = (struct vring_used *)base;
|
||||
|
||||
/* Mark queue as allocated, and start at 0 when we use it. */
|
||||
vq->vq_flags = VQ_ALLOC;
|
||||
vq->vq_last_avail = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vtblk_thread(void *arg)
|
||||
{
|
||||
struct beri_vtblk_softc *sc;
|
||||
int err;
|
||||
|
||||
sc = arg;
|
||||
|
||||
sx_xlock(&sc->sc_mtx);
|
||||
for (;;) {
|
||||
err = msleep(sc, &sc->sc_mtx, PCATCH | PZERO, "prd", hz);
|
||||
vtblk_notify(sc);
|
||||
}
|
||||
sx_xunlock(&sc->sc_mtx);
|
||||
|
||||
kthread_exit();
|
||||
}
|
||||
|
||||
static int
|
||||
backend_info(struct beri_vtblk_softc *sc)
|
||||
{
|
||||
struct virtio_blk_config *cfg;
|
||||
uint32_t *s;
|
||||
int reg;
|
||||
int i;
|
||||
|
||||
/* Specify that we provide block device */
|
||||
reg = htobe32(VIRTIO_ID_BLOCK);
|
||||
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
|
||||
|
||||
/* Queue size */
|
||||
reg = htobe32(NUM_DESCS);
|
||||
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
|
||||
|
||||
/* Our features */
|
||||
reg = htobe32(VIRTIO_RING_F_INDIRECT_DESC
|
||||
| VIRTIO_BLK_F_BLK_SIZE
|
||||
| VIRTIO_BLK_F_SEG_MAX);
|
||||
WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg);
|
||||
|
||||
cfg = sc->cfg;
|
||||
cfg->capacity = htobe64(sc->mdio->md_mediasize / DEV_BSIZE);
|
||||
cfg->size_max = 0; /* not negotiated */
|
||||
cfg->seg_max = htobe32(VTBLK_MAXSEGS);
|
||||
cfg->blk_size = htobe32(DEV_BSIZE);
|
||||
|
||||
s = (uint32_t *)cfg;
|
||||
|
||||
for (i = 0; i < sizeof(struct virtio_blk_config); i+=4) {
|
||||
WRITE4(sc, VIRTIO_MMIO_CONFIG + i, *s);
|
||||
s+=1;
|
||||
}
|
||||
|
||||
strncpy(sc->ident, "Virtio block backend", sizeof(sc->ident));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vtblk_intr(void *arg)
|
||||
{
|
||||
struct beri_vtblk_softc *sc;
|
||||
int pending;
|
||||
int reg;
|
||||
|
||||
sc = arg;
|
||||
|
||||
reg = PIO_READ(sc->pio_recv);
|
||||
|
||||
/* Ack */
|
||||
PIO_SET(sc->pio_recv, reg, 0);
|
||||
|
||||
pending = htobe32(reg);
|
||||
|
||||
if (pending & Q_PFN) {
|
||||
vq_init(sc);
|
||||
}
|
||||
|
||||
if (pending & Q_NOTIFY) {
|
||||
wakeup(sc);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
beri_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
struct beri_vtblk_softc *sc;
|
||||
int err;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
switch (cmd) {
|
||||
case MDIOCATTACH:
|
||||
/* take file as argument */
|
||||
if (sc->vnode != NULL) {
|
||||
/* Already opened */
|
||||
return (1);
|
||||
}
|
||||
sc->mdio = (struct md_ioctl *)addr;
|
||||
backend_info(sc);
|
||||
DPRINTF("opening file, td 0x%08x\n", (int)td);
|
||||
err = open_file(sc, td);
|
||||
if (err)
|
||||
return (err);
|
||||
PIO_SETUP_IRQ(sc->pio_recv, vtblk_intr, sc);
|
||||
sc->opened = 1;
|
||||
break;
|
||||
case MDIOCDETACH:
|
||||
if (sc->vnode == NULL) {
|
||||
/* File not opened */
|
||||
return (1);
|
||||
}
|
||||
sc->opened = 0;
|
||||
DPRINTF("closing file, td 0x%08x\n", (int)td);
|
||||
err = close_file(sc, td);
|
||||
if (err)
|
||||
return (err);
|
||||
PIO_TEARDOWN_IRQ(sc->pio_recv);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cdevsw beri_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_ioctl = beri_ioctl,
|
||||
.d_name = "virtio block backend",
|
||||
};
|
||||
|
||||
static int
|
||||
beri_vtblk_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-vtblk"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "SRI-Cambridge BERI block");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
beri_vtblk_attach(device_t dev)
|
||||
{
|
||||
struct beri_vtblk_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, beri_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
sc->cfg = malloc(sizeof(struct virtio_blk_config),
|
||||
M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
|
||||
sx_init(&sc->sc_mtx, device_get_nameunit(sc->dev));
|
||||
|
||||
error = kthread_add(vtblk_thread, sc, NULL, &sc->vtblk_ktd,
|
||||
0, 0, "beri_virtio_block");
|
||||
if (error) {
|
||||
device_printf(dev, "cannot create kthread\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
|
||||
return (ENXIO);
|
||||
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
|
||||
return (ENXIO);
|
||||
|
||||
sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL,
|
||||
S_IRWXU, "beri_vtblk");
|
||||
if (sc->cdev == NULL) {
|
||||
device_printf(dev, "Failed to create character device.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->cdev->si_drv1 = sc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t beri_vtblk_methods[] = {
|
||||
DEVMETHOD(device_probe, beri_vtblk_probe),
|
||||
DEVMETHOD(device_attach, beri_vtblk_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t beri_vtblk_driver = {
|
||||
"beri_vtblk",
|
||||
beri_vtblk_methods,
|
||||
sizeof(struct beri_vtblk_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(beri_vtblk, simplebus, beri_vtblk_driver, 0, 0);
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014-2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BERI interface for Virtio MMIO bus.
|
||||
*
|
||||
* This driver provides interrupt-engine for software-implemented
|
||||
* Virtio MMIO backend.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/watchdog.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cache.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/beri/virtio/virtio_mmio_platform.h>
|
||||
#include <dev/virtio/mmio/virtio_mmio.h>
|
||||
#include <dev/altera/pio/pio.h>
|
||||
|
||||
#include "virtio_mmio_if.h"
|
||||
#include "pio_if.h"
|
||||
|
||||
static void platform_intr(void *arg);
|
||||
|
||||
struct virtio_mmio_platform_softc {
|
||||
struct resource *res[1];
|
||||
void *ih;
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
void (*intr_handler)(void *);
|
||||
void *ih_user;
|
||||
device_t pio_recv;
|
||||
device_t pio_send;
|
||||
int use_pio;
|
||||
};
|
||||
|
||||
static int
|
||||
setup_pio(struct virtio_mmio_platform_softc *sc, char *name, device_t *dev)
|
||||
{
|
||||
phandle_t pio_node;
|
||||
struct fdt_ic *ic;
|
||||
phandle_t xref;
|
||||
phandle_t node;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (OF_searchencprop(node, name, &xref,
|
||||
sizeof(xref)) == -1) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pio_node = OF_node_from_xref(xref);
|
||||
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
|
||||
if (ic->iph == pio_node) {
|
||||
*dev = ic->dev;
|
||||
PIO_CONFIGURE(*dev, PIO_OUT_ALL,
|
||||
PIO_UNMASK_ALL);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_mmio_platform_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "beri,virtio_mmio_platform"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Virtio MMIO platform");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_mmio_platform_attach(device_t dev)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
struct fdt_ic *fic;
|
||||
phandle_t node;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->use_pio = 1;
|
||||
|
||||
if ((setup_pio(sc, "pio-send", &sc->pio_send) != 0) ||
|
||||
(setup_pio(sc, "pio-recv", &sc->pio_recv) != 0))
|
||||
sc->use_pio = 0;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
fic = malloc(sizeof(*fic), M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
fic->iph = node;
|
||||
fic->dev = dev;
|
||||
SLIST_INSERT_HEAD(&fdt_ic_list_head, fic, fdt_ics);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
platform_prewrite(device_t dev, size_t offset, int val)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
switch (offset) {
|
||||
case (VIRTIO_MMIO_QUEUE_NOTIFY):
|
||||
mips_dcache_wbinv_all();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
platform_note(device_t dev, size_t offset, int val)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
int note;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
switch (offset) {
|
||||
case (VIRTIO_MMIO_QUEUE_NOTIFY):
|
||||
if (val == 0)
|
||||
note = Q_NOTIFY;
|
||||
else if (val == 1)
|
||||
note = Q_NOTIFY1;
|
||||
else
|
||||
note = 0;
|
||||
break;
|
||||
case (VIRTIO_MMIO_QUEUE_PFN):
|
||||
note = Q_PFN;
|
||||
break;
|
||||
case (VIRTIO_MMIO_QUEUE_SEL):
|
||||
note = Q_SEL;
|
||||
break;
|
||||
default:
|
||||
note = 0;
|
||||
}
|
||||
|
||||
if (note) {
|
||||
mips_dcache_wbinv_all();
|
||||
|
||||
if (!sc->use_pio)
|
||||
return (0);
|
||||
|
||||
PIO_SET(sc->pio_send, note, 1);
|
||||
|
||||
/*
|
||||
* Wait until host ack the request.
|
||||
* Usually done within few cycles.
|
||||
* TODO: bad
|
||||
*/
|
||||
|
||||
for (i = 100; i > 0; i--) {
|
||||
if (PIO_READ(sc->pio_send) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
device_printf(sc->dev, "Warning: host busy\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
platform_intr(void *arg)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
int reg;
|
||||
|
||||
sc = arg;
|
||||
|
||||
if (sc->use_pio) {
|
||||
/* Read pending */
|
||||
reg = PIO_READ(sc->pio_recv);
|
||||
|
||||
/* Ack */
|
||||
PIO_SET(sc->pio_recv, reg, 0);
|
||||
}
|
||||
|
||||
/* Writeback, invalidate cache */
|
||||
mips_dcache_wbinv_all();
|
||||
|
||||
if (sc->intr_handler != NULL)
|
||||
sc->intr_handler(sc->ih_user);
|
||||
}
|
||||
|
||||
static int
|
||||
platform_setup_intr(device_t dev, device_t mmio_dev,
|
||||
void *intr_handler, void *ih_user)
|
||||
{
|
||||
struct virtio_mmio_platform_softc *sc;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->intr_handler = intr_handler;
|
||||
sc->ih_user = ih_user;
|
||||
|
||||
if (sc->use_pio) {
|
||||
PIO_SETUP_IRQ(sc->pio_recv, platform_intr, sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (!sc->res[0]) {
|
||||
device_printf(dev, "Can't allocate interrupt\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, platform_intr, sc, &sc->ih)) {
|
||||
device_printf(dev, "Can't setup the interrupt\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
platform_poll(device_t dev)
|
||||
{
|
||||
|
||||
mips_dcache_wbinv_all();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t virtio_mmio_platform_methods[] = {
|
||||
DEVMETHOD(device_probe, virtio_mmio_platform_probe),
|
||||
DEVMETHOD(device_attach, virtio_mmio_platform_attach),
|
||||
|
||||
/* virtio_mmio_if.h */
|
||||
DEVMETHOD(virtio_mmio_prewrite, platform_prewrite),
|
||||
DEVMETHOD(virtio_mmio_note, platform_note),
|
||||
DEVMETHOD(virtio_mmio_poll, platform_poll),
|
||||
DEVMETHOD(virtio_mmio_setup_intr, platform_setup_intr),
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t virtio_mmio_platform_driver = {
|
||||
"virtio_mmio_platform",
|
||||
virtio_mmio_platform_methods,
|
||||
sizeof(struct virtio_mmio_platform_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(virtio_mmio_platform, simplebus, virtio_mmio_platform_driver,
|
||||
0, 0);
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define Q_NOTIFY 0x01
|
||||
#define Q_PFN 0x02
|
||||
#define Q_INTR 0x04
|
||||
#define Q_SEL 0x08
|
||||
#define Q_NOTIFY1 0x10
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by SRI International and the University of
|
||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
|
||||
* ("CTSRD"), as part of the DARPA CRASH research programme.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* /dts-v1/; */
|
||||
#include "socfpga_cyclone5_sockit.dts"
|
||||
|
||||
/ {
|
||||
model = "Terasic SoCkit";
|
||||
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
|
||||
|
||||
memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */
|
||||
< 0x00001000 0x1000 >, /* virtio block */
|
||||
< 0x00002000 0x1000 >; /* virtio net */
|
||||
|
||||
soc {
|
||||
/* Local timer */
|
||||
timer@fffec600 {
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
/* Global timer */
|
||||
global_timer: timer@fffec200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0xfffec200 0x20>;
|
||||
interrupts = <1 11 0xf04>;
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
beri_mem0: mem@d0000000 {
|
||||
compatible = "sri-cambridge,beri-mem";
|
||||
reg = <0xd0000000 0x10000000>; /* 256mb */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pio0: pio@c0020000 {
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0020000 0x1000>; /* recv */
|
||||
interrupts = < 76 >;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pio1: pio@c0021000 {
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0021000 0x1000>; /* send */
|
||||
interrupts = < 82 >; /* not in use on arm side */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pio2: pio@c0022000 {
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0022000 0x1000>; /* recv */
|
||||
interrupts = < 77 >;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pio3: pio@c0023000 {
|
||||
compatible = "altr,pio";
|
||||
reg = <0xc0023000 0x1000>; /* send */
|
||||
interrupts = < 83 >; /* not in use on arm side */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
beri_vtblk: vtblk@00001000 {
|
||||
compatible = "sri-cambridge,beri-vtblk";
|
||||
reg = <0x00001000 0x1000>;
|
||||
pio-recv = <&pio0>;
|
||||
pio-send = <&pio1>;
|
||||
beri-mem = <&beri_mem0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
beri_vtnet: vtnet@00002000 {
|
||||
compatible = "sri-cambridge,beri-vtnet";
|
||||
reg = <0x00002000 0x1000>;
|
||||
pio-recv = <&pio2>;
|
||||
pio-send = <&pio3>;
|
||||
beri-mem = <&beri_mem0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
beri_debug: ring@c0000000 {
|
||||
compatible = "sri-cambridge,beri-ring";
|
||||
reg = <0xc0000000 0x3000>;
|
||||
interrupts = < 72 73 >;
|
||||
device_name = "beri_debug";
|
||||
data_size = <0x1000>;
|
||||
data_read = <0x0>;
|
||||
data_write = <0x1000>;
|
||||
control_read = <0x2000>;
|
||||
control_write = <0x2010>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
beri_console: ring@c0004000 {
|
||||
compatible = "sri-cambridge,beri-ring";
|
||||
reg = <0xc0004000 0x3000>;
|
||||
interrupts = < 74 75 >;
|
||||
device_name = "beri_console";
|
||||
data_size = <0x1000>;
|
||||
data_read = <0x0>;
|
||||
data_write = <0x1000>;
|
||||
control_read = <0x2000>;
|
||||
control_write = <0x2010>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdin = "serial0";
|
||||
stdout = "serial0";
|
||||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
bus-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
clock-frequency = <100000000>;
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Doxyfile 1.5.2
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = "FreeBSD kernel altera device code"
|
||||
OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_altera/
|
||||
EXTRACT_ALL = YES # for undocumented src, no warnings enabled
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = $(DOXYGEN_SRC_PATH)/dev/altera/ \
|
||||
$(NOTREVIEWED)
|
||||
|
||||
GENERATE_TAGFILE = dev_altera/dev_altera.tag
|
||||
|
||||
@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH)
|
||||
@INCLUDE = common-Doxyfile
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Doxyfile 1.5.2
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = "FreeBSD kernel beri device code"
|
||||
OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_beri/
|
||||
EXTRACT_ALL = YES # for undocumented src, no warnings enabled
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = $(DOXYGEN_SRC_PATH)/dev/beri/ \
|
||||
$(NOTREVIEWED)
|
||||
|
||||
GENERATE_TAGFILE = dev_beri/dev_beri.tag
|
||||
|
||||
@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH)
|
||||
@INCLUDE = common-Doxyfile
|
||||
|
||||
Loading…
Reference in a new issue