Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

fs/sysfs: MIPS: Don't translate all IOCTLs #402

Merged
merged 3 commits into from
Feb 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions cmd/periph-smoketest/spismoketest/spismoketest.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ import (
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spireg"
"periph.io/x/periph/host/fs"
)

var (
iorMode = fs.IOR('k', 1, 1)
iorLSBFirst = fs.IOR('k', 2, 1)
iorBitsPerWord = fs.IOR('k', 3, 1)
iorMaxSpeedHz = fs.IOR('k', 4, 4)
)

// SmokeTest is imported by periph-smoketest.
Expand Down Expand Up @@ -69,6 +77,15 @@ func (s *SmokeTest) Run(f *flag.FlagSet, args []string) error {
return fmt.Errorf("error setting SPI parameters: %v", err)
}

type flagGetter interface{ GetFlag(uint) (uint64, error) }
mode, err := c.(flagGetter).GetFlag(iorMode)
if err != nil {
return fmt.Errorf("failed to read back mode: %v", err)
}
if spi.Mode(mode) != spi.Mode0 {
return fmt.Errorf("read back mode doesn't match spi.Mode0: %v", spi.Mode(mode))
}

// Open the WC pin.
var wpPin gpio.PinIO
if *wp != "" {
Expand Down
30 changes: 0 additions & 30 deletions host/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,6 @@ type File struct {

// Ioctl sends an ioctl to the file handle.
func (f *File) Ioctl(op uint, data uintptr) error {
if isMIPS {
var err error
if op, err = translateOpMIPS(op); err != nil {
return err
}
}
return ioctl(f.Fd(), op, data)
}

Expand Down Expand Up @@ -104,27 +98,3 @@ var (
inhibited bool
used bool
)

func translateOpMIPS(op uint) (uint, error) {
// Decode the arm/x64 encoding and reencode as MIPS specific linux ioctl.
// arm/x64: DIR(2), SIZE(14), TYPE(8), NR(8)
// mips: DIR(3), SIZE(13), TYPE(8), NR(8)
// Check for size overflow.
if (op & (1 << (13 + 8 + 8))) != 0 {
return 0, errors.New("fs: op code size is too large")
}
const mask = (1 << (13 + 8 + 8)) - 1
out := op & mask
// Convert dir.
switch op >> (14 + 8 + 8) {
case 0: // none
out |= 1 << (13 + 8 + 8)
case 1: // write
out |= 4 << (13 + 8 + 8)
case 2: // read
out |= 2 << (13 + 8 + 8)
default:
return 0, errors.New("fs: op code dir is invalid")
}
return out, nil
}
42 changes: 0 additions & 42 deletions host/fs/fs_test.go

This file was deleted.

51 changes: 51 additions & 0 deletions host/fs/ioctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2019 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package fs

// These constants, variables and functions are ported from the Linux userland
// API header ioctl.h (commonly packaged at /usr/include/linux/ioctl.h which
// includes /usr/include/asm-generic/ioctl.h).

const (
iocNrbits uint = 8
iocTypebits uint = 8

iocNrshift uint = 0

iocTypeshift = iocNrshift + iocNrbits
iocSizeshift = iocTypeshift + iocTypebits
iocDirshift = iocSizeshift + iocSizebits
)

func ioc(dir, typ, nr, size uint) uint {
return (dir << iocDirshift) |
maruel marked this conversation as resolved.
Show resolved Hide resolved
(typ << iocTypeshift) |
(nr << iocNrshift) |
(size << iocSizeshift)
}

// IO defines an ioctl with no parameters. It corresponds to _IO in the Linux
// userland API.
func IO(typ, nr uint) uint {
return ioc(iocNone, typ, nr, 0)
}

// IOR defines an ioctl with read (userland perspective) parameters. It
// corresponds to _IOR in the Linux userland API.
func IOR(typ, nr, size uint) uint {
return ioc(iocRead, typ, nr, size)
}

// IOW defines an ioctl with write (userland perspective) parameters. It
// corresponds to _IOW in the Linux userland API.
func IOW(typ, nr, size uint) uint {
return ioc(iocWrite, typ, nr, size)
}

// IOWR defines an ioctl with both read and write parameters. It corresponds to
// _IOWR in the Linux userland API.
func IOWR(typ, nr, size uint) uint {
return ioc(iocRead|iocWrite, typ, nr, size)
}
9 changes: 8 additions & 1 deletion host/fs/ioctl_mips_like.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@

package fs

const isMIPS = true
const (
iocNone uint = 1
iocRead uint = 2
iocWrite uint = 4

iocSizebits uint = 13
iocDirbits uint = 3
)
9 changes: 8 additions & 1 deletion host/fs/ioctl_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@

package fs

const isMIPS = false
const (
iocNone uint = 0
iocWrite uint = 1
iocRead uint = 2

iocSizebits uint = 14
iocDirbits uint = 2
)
63 changes: 17 additions & 46 deletions host/sysfs/spi.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,21 +412,14 @@ func (s *spiConn) txPackets(p []spi.Packet) error {
}

func (s *spiConn) setFlag(op uint, arg uint64) error {
if err := s.f.Ioctl(op|0x40000000, uintptr(unsafe.Pointer(&arg))); err != nil {
svenschwermer marked this conversation as resolved.
Show resolved Hide resolved
return err
}
if false {
// Verification.
actual := uint64(0)
// getFlag() equivalent.
if err := s.f.Ioctl(op|0x80000000, uintptr(unsafe.Pointer(&actual))); err != nil {
return err
}
if actual != arg {
return fmt.Errorf("sysfs-spi: op 0x%x: set 0x%x, read 0x%x", op, arg, actual)
}
}
return nil
return s.f.Ioctl(op, uintptr(unsafe.Pointer(&arg)))
}

// GetFlag allows to read back flags set via a ioctl, i.e. setFlag. It is
// exported to allow calling it from the smoke test.
func (s *spiConn) GetFlag(op uint) (arg uint64, err error) {
err = s.f.Ioctl(op, uintptr(unsafe.Pointer(&arg)))
return
}

func (s *spiConn) initPins() {
Expand Down Expand Up @@ -469,42 +462,20 @@ const (
//
// Constants and structure definition can be found at
// /usr/include/linux/spi/spidev.h.
const (
spiIOCMode = 0x16B01 // SPI_IOC_WR_MODE (8 bits)
spiIOLSBFirst = 0x16B02 // SPI_IOC_WR_LSB_FIRST
spiIOCBitsPerWord = 0x16B03 // SPI_IOC_WR_BITS_PER_WORD
spiIOCMaxSpeedHz = 0x46B04 // SPI_IOC_WR_MAX_SPEED_HZ
spiIOCMode32 = 0x46B05 // SPI_IOC_WR_MODE32 (32 bits)
const spiIOCMagic uint = 'k'

var (
spiIOCMode = fs.IOW(spiIOCMagic, 1, 1) // SPI_IOC_WR_MODE (8 bits)
spiIOLSBFirst = fs.IOW(spiIOCMagic, 2, 1) // SPI_IOC_WR_LSB_FIRST
spiIOCBitsPerWord = fs.IOW(spiIOCMagic, 3, 1) // SPI_IOC_WR_BITS_PER_WORD
spiIOCMaxSpeedHz = fs.IOW(spiIOCMagic, 4, 4) // SPI_IOC_WR_MAX_SPEED_HZ
spiIOCMode32 = fs.IOW(spiIOCMagic, 5, 4) // SPI_IOC_WR_MODE32 (32 bits)
)

// spiIOCTx(l) calculates the equivalent of SPI_IOC_MESSAGE(l) to execute a
// transaction.
//
// The IOCTL for TX was deduced from this C code:
//
// #include "linux/spi/spidev.h"
// #include "sys/ioctl.h"
// #include <stdio.h>
// int main() {
// for (int i = 1; i < 10; i++) {
// printf("len(%d) = 0x%08X\n", i, SPI_IOC_MESSAGE(i));
// }
// return 0;
// }
//
// $ gcc a.cc && ./a.out
// len(1) = 0x40206B00
// len(2) = 0x40406B00
// len(3) = 0x40606B00
// len(4) = 0x40806B00
// len(5) = 0x40A06B00
// len(6) = 0x40C06B00
// len(7) = 0x40E06B00
// len(8) = 0x41006B00
// len(9) = 0x41206B00
func spiIOCTx(l int) uint {
op := uint(0x40006B00)
return op | uint(0x200000)*uint(l)
return fs.IOW(spiIOCMagic, 0, uint(l)*32)
}

// spiIOCTransfer is spi_ioc_transfer in linux/spi/spidev.h.
Expand Down
9 changes: 0 additions & 9 deletions host/sysfs/spi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,6 @@ func TestSPI_Connect_Half(t *testing.T) {
}
}

func TestSPIIOCTX(t *testing.T) {
if v := spiIOCTx(1); v != 0x40206B00 {
t.Fatalf("Expected 0x40206B00, got 0x%08X", v)
}
if v := spiIOCTx(9); v != 0x41206B00 {
t.Fatalf("Expected 0x41206B00, got 0x%08X", v)
}
}

func TestSPIDriver(t *testing.T) {
if len((&driverSPI{}).Prerequisites()) != 0 {
t.Fatal("unexpected SPI prerequisites")
Expand Down
3 changes: 2 additions & 1 deletion host/videocore/videocore.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ var (
mu sync.Mutex
mailbox messager
mailboxErr error

mbIoctl = fs.IOWR('d', 0, uint(unsafe.Sizeof(new(byte))))
)

const (
mbIoctl = 0xc0046400 //_IOWR(0x100, 0, char *)
// All of these return anything but zero (‽)
mbFirmwareVersion = 0x1 // 0, 4
mbBoardModel = 0x10001 // 0, 4
Expand Down