* O2 VICE support
@ 2002-12-10 19:11 ilya
2002-12-11 13:38 ` Christoph Hellwig
2002-12-22 9:20 ` Geert Uytterhoeven
0 siblings, 2 replies; 6+ messages in thread
From: ilya @ 2002-12-10 19:11 UTC (permalink / raw)
To: linux-mips; +Cc: ralf
[-- Attachment #1.1: Type: text/plain, Size: 135 bytes --]
Attached is patch set to add support to kernel for O2 video compression engine
(VICE). It should apply cleanly to latest CVS.
Ilya.
[-- Attachment #1.2: vice.diff --]
[-- Type: text/plain, Size: 53234 bytes --]
Index: arch/mips64/kernel/ioctl32.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/ioctl32.c,v
retrieving revision 1.26
diff -u -r1.26 ioctl32.c
--- arch/mips64/kernel/ioctl32.c 12 Nov 2002 15:26:11 -0000 1.26
+++ arch/mips64/kernel/ioctl32.c 10 Dec 2002 17:02:29 -0000
@@ -55,6 +57,10 @@
#include <linux/rtc.h>
+#ifdef CONFIG_O2_VICE
+#include <linux/vice.h>
+#endif
+
long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -827,6 +968,12 @@
COMPATIBLE_IOCTL(TIOCGSERIAL)
COMPATIBLE_IOCTL(TIOCSSERIAL)
COMPATIBLE_IOCTL(TIOCSERGETLSR)
+#ifdef CONFIG_O2_VICE
+COMPATIBLE_IOCTL(VICE_IOCTL_MAP_DMA)
+COMPATIBLE_IOCTL(VICE_IOCTL_MSP_RUN)
+COMPATIBLE_IOCTL(VICE_IOCTL_BSP_RUN)
+COMPATIBLE_IOCTL(VICE_IOCTL_DO_DMA)
+#endif
COMPATIBLE_IOCTL(FIOCLEX)
COMPATIBLE_IOCTL(FIONCLEX)
Index: drivers/char/Kconfig
===================================================================
RCS file: /home/cvs/linux/drivers/char/Kconfig,v
retrieving revision 1.1
diff -u -r1.1 Kconfig
--- drivers/char/Kconfig 2 Nov 2002 20:01:57 -0000 1.1
+++ drivers/char/Kconfig 10 Dec 2002 17:02:31 -0000
@@ -1281,6 +1281,8 @@
source "drivers/char/pcmcia/Kconfig"
+source drivers/char/o2vice/Kconfig
+
config MWAVE
tristate "ACP Modem (Mwave) support"
depends on X86
Index: drivers/char/Makefile
===================================================================
RCS file: /home/cvs/linux/drivers/char/Makefile,v
retrieving revision 1.100
diff -u -r1.100 Makefile
--- drivers/char/Makefile 12 Nov 2002 15:03:11 -0000 1.100
+++ drivers/char/Makefile 10 Dec 2002 17:02:31 -0000
@@ -111,6 +111,7 @@
obj-$(CONFIG_AGP) += agp/
obj-$(CONFIG_DRM) += drm/
obj-$(CONFIG_PCMCIA) += pcmcia/
+obj-$(CONFIG_O2_VICE) += o2vice/
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/Kconfig Sat Nov 2 14:10:16 2002
@@ -0,0 +1,32 @@
+#
+# O2 VICE Engine confiuration
+#
+
+config O2_VICE
+ tristate "O2 VICE Engine Support"
+ depends on SGI_IP32
+ ---help---
+ This option enables O2 VICE Engine support.
+ VICE stands for Video Image Compression Engine. This is very powerfull
+ piece of silicon, that can greatly speed up lots of graphics, vide, or
+ sound related tasks. To be able to use it, you will also need special
+ library, that can be found at <insert URL here>
+
+config O2_VICE_DBGG
+ bool "VICE Debugger Support. READ HELP!"
+ depends on O2_VICE
+ ---help---
+ This option enables features of VICE driver needed to debug VICE library.
+ This is probably serious security risk. You don't need it. If you think
+ you do, you are wrong. Say NO.
+
+config O2_VICE_DBG
+ bool "You seem to insist... did you read help? Yes? No? READ HELP!"
+ depends on O2_VICE_DBGG
+ ---help---
+ You are still here? Didn't I just tell you that it is not needed?
+ Or do you want to say you *legally* obtained information needed for
+ programming VICE? That you got all the tools needed? As a matter of
+ fact, these tools don't even exist yet!
+
+ Sigh... You've been warned...
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/Makefile Thu Sep 12 00:12:16 2002
@@ -0,0 +1,21 @@
+#
+# drivers/char/o2vice/Makefile
+#
+# Makefile for the O2 VICE Engine driver.
+#
+
+SUB_DIRS :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+#O_TARGET := vice.o
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_O2_VICE) += main.o msp.o bsp.o dma.o
+#obj-$(CONFIG_O2_VICE_DBG) += vicedebug.o
+
+include $(TOPDIR)/Rules.make
--- /dev/null Sun Jul 17 16:46:18 1994
+++ include/linux/vice.h Tue Dec 10 09:51:46 2002
@@ -0,0 +1,462 @@
+/*
+ * vice.h -- definitions for the SGI O2 VICE
+ *
+ * The code used as a template for 'vice' driver
+ * came from the book "Linux Device Drivers" by
+ * Alessandro Rubini and Jonathan Corbet,
+ * published by O'Reilly & Associates
+ *
+ * Copyright (C) 2002 Ilya Volynets
+ * Development was sponsored by Total Knowledge
+ * http://www.total-knowledge.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * =====================================================================
+ * 09.16.2002 - iluxa
+ * - MSP and DMA units mostly work.
+ * - Simple ioctl interface to managing I/O buffers (just 2 4M buffers)
+ */
+
+#ifndef _VICE_H_
+#define _VICE_H_
+
+#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
+#ifdef __KERNEL__
+#include <asm/pci.h>
+#endif
+#include <linux/types.h> /* size_t */
+
+#ifndef __KERNEL__
+typedef __u64 u64;
+typedef __u32 u32;
+typedef __u16 u16;
+#endif /* __KERNEL */
+
+/*
+ * Macros to help debugging
+ */
+
+#ifdef __KERNEL__
+
+#define VICE_DEBUG 1
+
+#undef DPRINTK /* undef it, just in case */
+#ifdef VICE_DEBUG
+# define DPRINTK(fmt, args...) printk( KERN_DEBUG "vice: " fmt, ## args)
+#else
+# define DPRINTK(fmt, args...) /* not debugging: nothing */
+#endif
+
+#define PDEBUG DPRINTK
+
+#ifndef VICE_MAJOR
+#define VICE_MAJOR 240 /* dynamic major by default */
+#endif
+
+#define VICE_VICE 0 /* main vice device, debug, stream data through, etc. */
+
+#define VICE_MAX_TYPE 1 /* always define it to be max possible minor nr for this driver */
+
+
+#include <linux/devfs_fs_kernel.h>
+
+#include <asm/ip32/crime.h>
+
+extern devfs_handle_t vice_devfs_dir;
+/*
+ * Prototypes for shared functions
+ */
+ssize_t vice_read (struct file *filp, char *buf, size_t count,
+ loff_t *f_pos);
+ssize_t vice_write (struct file *filp, const char *buf, size_t count,
+ loff_t *f_pos);
+loff_t vice_llseek (struct file *filp, loff_t off, int whence);
+int vice_ioctl (struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+#endif /* __KERNEL__ */
+
+#define VICE_MAX_DMA_BUFFERS 1024 /* Max number of VICE_PAGE_SIZE pages that can be MMAPed by userland */
+ /* Affects size of page table */
+
+#define VICE_BASE 0x17000000 /*Physical address...*/
+#define VICE_REG(reg) (VICE_BASE|(reg)) /*access vice register*/
+#define VICE_IO_MAX_OFFSET 0xEFFF /* Max offset mapped to registers (TLB is *not* accessible to userspace) */
+#define VICE_MIN_OFFSET 0x10000 /* Min offset mapped to RAM */
+#define VICE_MAX_OFFSET VICE_MIN_OFFSET+0x800000/* Max offset mapped to RAM */
+
+#ifndef BIT
+#define BIT(x) (0x1<<x)
+#endif /* !defined BIT */
+/*
+ * VICE Register definitions
+ */
+
+#define VICE_ID 0x0008 /* VICE revision id size 8 ro */
+#define VICE_CFG 0xE000 /* VICE config register size 16 rw */
+#define VICE_INT_RESET 0xE008 /* VICE reset interrupt size 9 wo */
+#define VICE_INT_EN 0xE010 /* VICE interrupt enable size 9 rw */
+#define HST_BSP_IN_BOX 0x0028 /* Host copy of BSP/MSP inbox size 16 ro */
+#define HST_BSP_OUT_BOX 0x0030 /* Host copy of BSP/MSP outbox size 16 ro */
+#define MSP_CTL_STAT 0x0040 /* MSP Control/Status register size 32 rw */
+#define MSP_EXPT_FLAG 0x0048 /* MSP Exception flag size 32 rw */
+#define MSP_PC 0x0050 /* MSP Program Counter size 32 rw */
+#define MSP_BAD_ADDR 0x0058 /* MSP Bad Address size 32 ro */
+#define MSP_WATCH_POINT 0x0060 /* MSP Watch Point address size 32 rw */
+#define MSP_EPC 0x0068 /* MSP Exception PC size 32 ro */
+#define MSP_CAUSE 0x0070 /* MSP Exception Cause size 32 ro */
+#define BSP_RPAGE 0x0078 /* BSP R Page size 16 rw */
+#define BSP_SW_INT 0x0080 /* BSP Software Interrupt size 0 wo */
+#define MSP_D_RAM 0x0100 /* MSP Data RAM Arbitration register size 32 rw */
+#define VICEMSP_COUNT 0x0108 /* MSP Free Running Counter size 32 ro */
+#define BSP_CTL_STAT 0x0110 /* BSP Control/Status register size 16 rw */
+#define BSP_WATCH_POINT 0x0118 /* BSP Watch Point size 16 rw */
+#define BSP_IN_COUNT 0x0120 /* BSP Decoded Bits counter size 24 ro */
+#define BSP_OUT_COUNT 0x0128 /* BSP Encoded Bits counter size 24 ro */
+#define BSP_PC 0x0140 /* BSP Program Counter size 16 rw */
+#define BSP_EPC 0x0148 /* BSP Exception PC size 16 rw */
+#define BSP_HALT_RESET 0x0150 /* BSP Halt/Reset Register size 2 ro */
+#define BSP_CAUSE 0x0158 /* BSP Exception Cause size 16 ro */
+#define VICE_INT 0x0160 /* Interruot and Status size 9 ro */
+#define BSP_FIFO_CTL_STAT 0x0168 /* BSP FIFO Control/Status size 6 rw */
+/* 0x170, 0x178 -?? */
+#define DMA_CH1_CTL 0x0180 /* DMA Chennel 1 Control size 16 rw */
+#define DMA_CH1_STAT 0x0188 /* DMA Channel 1 Status size 16 ro */
+#define DMA_CH1_DATA 0x0190 /* DMA Channel 1 Fill Pattern size 16 rw */
+#define DMA_CH1_MEM_PTR 0x0198 /* DMA Channel 1 Sys Mem Ptr size 32 ro */
+#define DMA_CH1_VICE_PTR 0x01A0 /* DMA Channel 1 VICE Mem Ptr size 16 ro */
+#define DMA_CH1_COUNT 0x01A8 /* DMA Channel 1 remaining count size 16 ro */
+/*0x01B0 -- unused */
+#define MSP_SW_INT 0x01B8 /* MSP Software Interrupt size 0 wo */
+#define DMA_CH2_CTL 0x01C0 /* DMA Chennel 2 Control size 16 rw */
+#define DMA_CH2_STAT 0x01C8 /* DMA Channel 2 Status size 16 ro */
+#define DMA_CH2_DATA 0x01D0 /* DMA Channel 2 Fill Pattern size 16 rw */
+#define DMA_CH2_MEM_PTR 0x01D8 /* DMA Channel 2 Sys Mem Ptr size 32 ro */
+#define DMA_CH2_VICE_PTR 0x01E0 /* DMA Channel 2 VICE Mem Ptr size 16 ro */
+#define DMA_CH2_COUNT 0x01E8 /* DMA Channel 2 remaining count size 16 ro */
+#define BSP_INBOX 0x01F0 /* BSP inbox size 16 ro */
+#define BSP_OUTBOX 0x01F8 /* BSP outbox size 16 rw */
+
+/* VICE RAM's */
+#define MSP_IRAM 0x2000 /* MSP instruction RAM base, length 4K */
+#define BSP_IRAM 0x4000 /* BSP instruction RAM base, length 4K */
+#define BSP_TABLE 0x5000 /* BSP Tables, length 8K */
+#define BSP_IO_IN 0x7800 /* BSP Input buffers, length 2K */
+#define BSP_IO_OUT 0x7000 /* BSP Output buffers, length 2K */
+#define VICE_DRAM_A 0x8000 /* Data RAM Bank A, , length 2K */
+#define VICE_DRAM_B 0x8800 /* Data RAM Bank B, , length 2K */
+#define VICE_DRAM_C 0x9000 /* Data RAM Bank C, , length 2K */
+
+/* VICE Interrupt status bits */
+#define VICE_INT_DMA_CH1_DONE BIT(0)
+#define VICE_INT_DMA_CH1_ERR BIT(1)
+#define VICE_INT_MSP_SW BIT(2) /* MSP wants to interrupt host (Program is finished?) */
+#define VICE_INT_MSP_ERR BIT(3) /* MSP exception */
+#define VICE_INT_BSP_SW BIT(4) /* BSP wants to interrupt host (Program is finished?) */
+#define VICE_INT_BSP_ERR BIT(5) /* BSP exception */
+#define VICE_INT_BUSERR BIT(6) /* ?? Erroneous data received through SysAD interface */
+#define VICE_INT_DMA_CH2_DONE BIT(7)
+#define VICE_INT_DMA_CH2_ERR BIT(8)
+
+/*
+ * VICE DMA Describtor related definitions
+ */
+
+/* Flags */
+#define VICE_DMA_HALT BIT(15)
+#define VICE_DMA_SKIP BIT(14)
+#define VICE_DMA_TOVICE BIT(13) /* 1=transaction is System->VICE, 0=VICE->System */
+#define VICE_DMA_FILL BIT(12) /* 1=Pattern fill VICE memory from VICEDMA_DATA register \
+ 0=normal VICE<->System transaction */
+/* flags (11:10) */
+#define VICE_DMA_YC_NONE (0x0<<10) /* Just plain pump it through */
+#define VICE_DMA_YC_422_420 (0x1<<10) /* Y/C 4:2:2 to Y/C 4:2:0 split */
+#define VICE_DMA_YC_422_422 (0x2<<10) /* Y/C 4:2:2 to Y/C 4:2:2 split */
+#define VICE_DMA_YC_422_Y (0x3<<10) /* Y/C 4:2:2 to Y split -- DMA read only */
+
+/* flags(9:8) */
+#define VICE_DMA_HP_FF (0x0<<8) /* Full Pel Vert Full Pel Horz */
+#define VICE_DMA_HP_FH (0x1<<8) /* Full Pel Vert Half Pel Horz */
+#define VICE_DMA_HP_HF (0x2<<8) /* Half Pel Vert Full Pel Horz */
+#define VICE_DMA_HP_HH (0x3<<8) /* Half Pel Vert Half Pel Horz */
+
+#define VICE_DMA_ILV BIT(7) /* 0=Process describtor individually, \
+ 1=Pcocess describtors as pairs and \
+ interleave them into VICE memory */
+/* Source/Destination location within VICE FLAGS(6:4)*/
+#define VICE_DMA_LOC_DRAMA (0x0<<4) /* Data RAM A */
+#define VICE_DMA_LOC_DRAMB (0x1<<4) /* Data RAM B */
+#define VICE_DMA_LOC_DRAMC (0x2<<4) /* Data RAM C */
+#define VICE_DMA_LOC_MSPI (0x3<<4) /* MSP Instruction RAM */
+#define VICE_DMA_LOC_BSPI (0x4<<4) /* BSP Instruction RAM */
+#define VICE_DMA_LOC_BSPTBL (0x5<<4) /* BSP Table RAM */
+#define VICE_DMA_LOC_BSPFIFO (0x6<<4) /* BSP Decode FIFO */
+#define VICE_DMA_LOC_TLB (0x7<<4) /* DMA TLB RAM */
+
+#define VICE_DMA_HPEN BIT(3) /* 0=Half Pel mode disabled -- ignore 8:9 */
+
+typedef struct vice_dma_desc
+{
+ u64 flags; /* See above for definitions of various bits */
+ u64 sys_addr_hi; /* High word of system memory address */
+ u64 sys_addr_lo; /* Low word of system memory address */
+ u64 span; /* Length of one line */
+ u64 stride; /* Number of bytes to skip between lines */
+ u64 line_count; /* Number of lines */
+ u64 vice_addr_Y; /* VICE memory address */
+ u64 vice_addr_C; /* VICE mem address for Y/C translated mode transfers */
+} vice_dma_desc;
+
+#define DMA_DESCRIBTORS_BASE 0x1000
+#define VICE_DMA_DESC(x) (DMA_DESCRIBTORS_BASE+((x)*sizeof(vice_dma_desc)))
+
+/*
+ * VICE DMA has eight descriptors -- 4 for each channel
+ */
+#define VICE_DMA_CH1_D1 VICE_DMA_DESC(0)
+#define VICE_DMA_CH1_D2 VICE_DMA_DESC(1)
+#define VICE_DMA_CH1_D3 VICE_DMA_DESC(2)
+#define VICE_DMA_CH1_D4 VICE_DMA_DESC(3)
+#define VICE_DMA_CH2_D1 VICE_DMA_DESC(4)
+#define VICE_DMA_CH2_D2 VICE_DMA_DESC(5)
+#define VICE_DMA_CH2_D3 VICE_DMA_DESC(6)
+#define VICE_DMA_CH2_D4 VICE_DMA_DESC(7)
+
+/* VICE DMA control register bits */
+#define VICE_DMA_CTL_GO BIT(0) /* Write 1 to kick off DMA */
+#define VICE_DMA_CTL_IE BIT(1) /* 1=Interrupt on DMA completion, 0=No interrupt */
+#define VICE_DMA_CTL_STOP BIT(2) /* Write 1 to stop DMA */
+#define VICE_DMA_CTL_RESET BIT(3) /* 1=Reset DMA engine, write 0 to allow it to run again */
+#define VICE_DMA_CTL_DESC1 BIT(4) /* Start DMA with descriptor 1 */
+#define VICE_DMA_CTL_DESC2 BIT(5) /* Start DMA with descriptor 2 */
+#define VICE_DMA_CTL_DESC3 BIT(6) /* Start DMA with descriptor 3 */
+#define VICE_DMA_CTL_DESC4 BIT(7) /* Start DMA with descriptor 4 */
+#define VICE_DMA_CTL_TLB_BYPASS BIT(8) /* Bypass TLB for this transaction */
+#define VICE_DMA_CTL_FLUSH_BUF BIT(9) /* What the hell does this do? */
+
+/*
+ * DMA TLB definitions
+ */
+
+#define VICE_PAGE_SHIFT 16
+#define VICE_PAGE_ORDER 4
+#define VICE_PAGE_SIZE (1<<VICE_PAGE_SHIFT)
+#define VICE_PAGE_MASK 0xFFFF0000 /* VICE DMA TLB works with 64K pages aligned on 64K boundary */
+#define VICE_TLB_OFFSET 0xF000 /* Vice TLB starts here. Range is F000-FFFC */
+#define VICE_TLB_ENTRIES 64 /* Number of TLB entried in VICE */
+
+#define VICE_DMA_LINEAR 0x00800000 /* Linear access to system memory */
+#define VICE_DMA_TILED 0x10800000 /* Tiled access to system memory */
+
+/*
+ * TLB Entry format
+ */
+#define VICE_TLB_VALID BIT(0)
+#define VICE_TLB_WRITABLE BIT(1)
+
+/*
+ * MSP definitions
+ */
+
+#define MSP_GO BIT(0) /* writing MSP_GO to MSP_CTL_STAT register starts MSP */
+#define MSP_OPERATIONAL BIT(1) /* Actually you have to write 1 to take it out of reset... Ugh */
+
+/*
+ * BSP definitions
+ */
+#define BSP_OPERATIONAL BIT(0) /* write 1 to take BSP out of reset */
+#define BSP_HALT BIT(1) /* write 0 to start BSP, write 1 to halt it */
+#define BSP_HALT_ACK BIT(2) /* reads as 1, when BSP recognised HALT request */
+
+#define BSP_FIFO_CTL_RESET BIT(2)
+
+#define MAX_BSP_HALT_WAIT 10 /*max time to vait for BSP halt before reset */
+
+/*
+ * VICE IOCTL related definitions
+ */
+#define VICE_RES_STATUS_FREE 0
+#define VICE_RES_STATUS_INPROGRESS 1
+#define VICE_RES_STATUS_DONE 2
+#define VICE_RES_STATUS_ERR 3
+
+
+typedef struct dma_run
+{
+ u32 channel;
+ u32 desc;
+ u32 status;
+} dma_run;
+
+typedef struct msp_run
+{
+ u32 pc; /* PC, where MSP have finished running (either took exception, or did SW int) */
+ u32 reason; /* MSP_EXPT_CAUSE */
+ u32 status; /* Whether MSP took exception or did SW int */
+} msp_run;
+
+typedef struct bsp_run
+{
+ u32 pc;
+ u32 reason;
+ u32 status;
+} bsp_run;
+
+/* Must be written all at once. Should I make a union of it with u32? */
+typedef struct vice_tlb_entry
+{
+ u16 page_num; /* Physical 64K page number */
+ u16 flags; /* Bit 0 - valid, bit 1 writable, rest undefined */
+} vice_tlb_entry;
+
+
+#ifdef __KERNEL__
+struct vice_dev;
+
+typedef struct vice_dev {
+ char is_open;
+ struct semaphore sem; /* mutual exclusion semaphore */
+ devfs_handle_t handle; /* only used if devfs is there */
+ vice_dma_desc* ch1; /* current DMA decriptor for channel 1 */
+ vice_dma_desc* ch2; /* current DMA decriptor for channel 2 */
+
+ u32 ch1_dma_stat; /* Various flags related to DMA in progress */
+ u32 ch2_dma_stat; /* Various flags related to DMA in progress */
+
+ spinlock_t dma_lock[2]; /* spinlocks for accessing dma status for 2 VICE DMA channels */
+ u32 dma_status[2]; /* status of dma channels */
+
+ dma_addr_t dma_mem[VICE_TLB_ENTRIES*2]; /* 2 sets 64*64K pages, used for DMA to/from VICE */
+ void* dma_kmem[VICE_TLB_ENTRIES*2]; /* 2 sets 64*64K pages, used for DMA to/from VICE */
+
+ /*
+ vice_page *page_table;
+ unsigned int page_cnt;
+ */
+ /* MSP stuff */
+ u32 msp_pc; /* PC where MSP stopped (EPC) */
+ u32 msp_int_reason; /* Reason MSP stopped */
+ u32 msp_status; /* Free/Working/Done/Error */
+ spinlock_t msp_lock; /* spinlock for accessing MSP status */
+
+ /* BSP stuff */
+ u32 bsp_pc; /* PC where BSP stopped (EPC) */
+ u32 bsp_int_reason; /* Reason BSP stopped */
+ u32 bsp_status; /* Free/Working/Done/Error */
+ spinlock_t bsp_lock; /* spinlock for accessing BSP status */
+} vice_dev;
+
+#endif /* __KERNEL__ */
+
+#define VICE_DMA_STAT_DATA BIT(0)
+#define VICE_DMA_STAT_MSP_CODE BIT(1)
+#define VICE_DMA_STAT_BSP_CODE BIT(2)
+#define VICE_DMA_STAT_BSP_TBL BIT(3)
+#define VICE_DMA_STAT_DIR BIT(4) /* 0 - to VICE, 1 to system */
+
+/*
+ * VICE ioctl commands
+ */
+#ifdef __KERNEL__
+#define VICE_IOCTL_MAGIC 0x96
+#define VICE_IOCTL_MAP_DMA _IOR(VICE_IOCTL_MAGIC,1,unsigned long)
+#define VICE_IOCTL_MSP_RUN _IOR(VICE_IOCTL_MAGIC,2,msp_run)
+#define VICE_IOCTL_BSP_RUN _IOR(VICE_IOCTL_MAGIC,3,bsp_run)
+#define VICE_IOCTL_DO_DMA _IOWR(VICE_IOCTL_MAGIC,4,dma_run)
+#else
+#define VICE_IOCTL_MAP_DMA 0x40089601
+#define VICE_IOCTL_MSP_RUN 0x400c9602
+#define VICE_IOCTL_BSP_RUN 0x400c9603
+#define VICE_IOCTL_DO_DMA 0xc00c9604
+#endif
+
+#ifdef __KERNEL__
+/* Vice wait queue */
+//Each unit has it's own wait_queue, as they might all sleep separately
+//extern wait_queue_head_t dma_wq;
+
+static inline void vice_write_reg(u32 reg,u64 value)
+{
+ *(volatile u64*)(KSEG1ADDR(VICE_REG(reg)))=value;
+}
+static inline u64 vice_read_reg(u32 reg)
+{
+ return *(volatile u64*)(KSEG1ADDR(VICE_REG(reg)));
+}
+
+static inline void vice_write_32(u32 addr,u32 value)
+{
+ *(volatile u32*)(KSEG1ADDR(VICE_REG(addr)))=value;
+}
+static inline u32 vice_read_32(u32 addr)
+{
+ return *(volatile u32*)(KSEG1ADDR(VICE_REG(addr)));
+}
+
+int vice_dma_map_set(vice_dev *vice,unsigned long set);
+
+/*
+ * Some DMA-related inline functions
+ */
+
+static inline int vice_dma_mem_init(vice_dev *vice)
+{
+ int i;
+ for (i=0; i<64*2;i++){
+ if(!(vice->dma_kmem[i]=pci_alloc_consistent(0,VICE_PAGE_SIZE,&(vice->dma_mem[i])))) {
+ DPRINTK("failed at page# %i\n",i);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+static inline void vice_dma_mem_free(vice_dev *vice)
+{
+ int i;
+ for (i=0; i<64*2;i++){
+ if(vice->dma_kmem[i]) {
+ pci_free_consistent(0,VICE_PAGE_ORDER,vice->dma_kmem[i],vice->dma_mem[i]);
+ vice->dma_kmem[i]=0;
+ vice->dma_mem[i]=0;
+ }
+ }
+}
+
+int vice_msp_init(vice_dev* vice);
+int vice_bsp_init(vice_dev* vice);
+int vice_dma_init(vice_dev* vice);
+
+void vice_msp_reset(vice_dev* vice);
+void vice_bsp_reset(vice_dev* vice);
+void vice_dma_reset(vice_dev* vice);
+
+void vice_msp_cleanup(vice_dev* vice);
+void vice_bsp_cleanup(vice_dev* vice);
+void vice_dma_cleanup(vice_dev* vice);
+
+void vice_dma_done(vice_dev* vice, int channel);
+void vice_dma_err(vice_dev* vice, int channel);
+void vice_handle_msp_int(vice_dev* vice);
+void vice_handle_msp_err(vice_dev* vice);
+void vice_handle_bsp_int(vice_dev* vice);
+void vice_handle_bsp_err(vice_dev* vice);
+void vice_handle_bus_err(vice_dev* vice);
+
+int vice_dma_run(vice_dev* vice,dma_run* run);
+int vice_msp_run(vice_dev* vice,msp_run* run);
+int vice_bsp_run(vice_dev* vice,bsp_run* run);
+#endif /* __KERNEL__ */
+
+#endif /* _VICE_H_ */
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/bsp.c Tue Dec 10 09:54:48 2002
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright (C) 2002 Ilya Volynets
+ * Sponsored by Total Knowledge
+ * http://www.total-knowledge.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *=======================================================================
+ * 09.16.2002 iluxa
+ * - skeleton only (I don't have instruction set for BSP, so there
+ * is no way I can test it).
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <asm/page.h>
+#include <linux/vmalloc.h> /* kmalloc() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h> /* O_ACCMODE */
+
+#include <asm/system.h> /* cli(), *_flags */
+#include <asm/pci.h>
+#include <asm/uaccess.h> /* put_user & friends */
+#include <asm/delay.h>
+
+/*
+ * The file operations for the bsp device
+ * (some are overlayed with primary vice)
+ */
+
+#include <linux/vice.h>
+
+
+/* wait queue to wait on while BSP runs */
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+void vice_bsp_reset(vice_dev* vice);
+
+/*
+ * Loads BSP PC with value form vice->bsp_pc, takes bsp out of reset
+ * state (just in case?) and kicks off execution.
+ */
+static inline void bsp_go(vice_dev* vice)
+{
+ vice_write_reg(BSP_HALT_RESET,BSP_OPERATIONAL); /* BSP_HALT=0 to start */
+}
+
+static inline void vice_bsp_stop()
+{
+ int i=0;
+ u64 ctl=vice_read_reg(BSP_HALT_RESET)|BSP_HALT;
+ vice_write_reg(BSP_HALT_RESET,ctl);
+ while(!vice_read_reg(BSP_HALT_RESET)&BSP_HALT_ACK) {
+ if (++i>MAX_BSP_HALT_WAIT) {
+ printk(KERN_WARNING "o2vice: timeout stopping bsp, bsp reset\n");
+ vice_bsp_reset(0);/*FIXME: pass vice* arrond*/
+ }
+ udelay(16);
+ }
+}
+
+int vice_bsp_init(struct vice_dev* vice)
+{
+ spin_lock_init(&vice->dma_lock[1]);
+ return 0;
+}
+
+void vice_bsp_reset(vice_dev* vice)
+{
+ vice_write_reg(BSP_HALT_RESET,0);
+ vice_write_reg(BSP_FIFO_CTL_STAT, BSP_FIFO_CTL_RESET);
+ udelay(1);
+ vice_write_reg(BSP_HALT_RESET, BSP_OPERATIONAL|BSP_HALT);
+ vice_write_reg(BSP_FIFO_CTL_STAT,0);
+}
+void vice_bsp_cleanup(vice_dev* vice)
+{
+ vice_bsp_stop();
+}
+
+void vice_handle_bsp_int(vice_dev* vice)
+{
+ DPRINTK("Ah! We are done with BSP!\n");
+ if(vice->bsp_status!=VICE_RES_STATUS_INPROGRESS) {
+ DPRINTK("Ugh... BSP interrupt while BSP isn't started from driver!\n");
+ return;
+ }
+ vice->bsp_status=VICE_RES_STATUS_DONE;
+ vice->bsp_pc=-1; /* No exception, no EPC, and PC is probably
+ not one which executed Exception instruction */
+ vice->bsp_int_reason=vice_read_reg(BSP_CAUSE);
+ wake_up_interruptible(&wq);
+}
+void vice_handle_bsp_err(vice_dev* vice)
+{
+ DPRINTK("Ouch! BSP Exception!\n");
+ if(vice->bsp_status!=VICE_RES_STATUS_INPROGRESS) {
+ DPRINTK("Ugh... BSP exception while BSP isn't started from driver!\n");
+ return;
+ }
+ vice->bsp_status=VICE_RES_STATUS_ERR;
+ vice->bsp_pc=(u32)vice_read_reg(BSP_EPC);
+ vice->bsp_int_reason=vice_read_reg(BSP_CAUSE);
+ wake_up_interruptible(&wq);
+}
+
+int vice_bsp_run(vice_dev* vice, bsp_run* result)
+{
+ bsp_run r;
+ if(!access_ok(VERIFY_WRITE,result,sizeof(bsp_run)))
+ return -EFAULT;
+ DPRINTK("Checking for BSP status\n");
+ spin_lock_irq(vice->bsp_lock);
+ if(vice->bsp_status!=VICE_RES_STATUS_FREE) {
+ spin_unlock_irq(vice->bsp_lock);
+ return -EBUSY;
+ }
+ DPRINTK("BSP is free\n");
+ vice->bsp_status=VICE_RES_STATUS_INPROGRESS;
+ spin_unlock_irq(vice->bsp_lock);
+ DPRINTK("Kicking BSP off\n");
+ bsp_go(vice);
+ /*
+ * Sleep, untill BSP interrupts us...
+ *
+ * No spinlock is needed...
+ */
+ DPRINTK("Falling asleep\n");
+ while(vice->bsp_status==VICE_RES_STATUS_INPROGRESS) {
+ interruptible_sleep_on(&wq);
+ DPRINTK("Huh? Where am I?\n");
+ if(signal_pending(current))break;
+ }
+ DPRINTK("*yawn* obviously waking up....\n");
+ copy_from_user(&r,result,sizeof(r));
+ DPRINTK("r.reason=%x, r.pc=%x, r.status=%x\n",r.reason,r.pc,r.status);
+ r.status=vice->bsp_status;
+ vice->bsp_status=VICE_RES_STATUS_FREE;
+ r.pc=vice->bsp_pc;
+ r.reason=vice->bsp_int_reason;
+ DPRINTK("r.reason=%x, r.pc=%x, r.status=%x\n",r.reason,r.pc,r.status);
+ return copy_to_user(result,&r,sizeof(r));
+}
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/msp.c Tue Dec 10 09:55:35 2002
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright (C) 2002 Ilya Volynets
+ * Sponsored by Total Knowledge
+ * http://www.total-knowledge.com
+ *
+ * Development of this code was made possible by generous contribution
+ * from Total Knowledge (http://www.total-knowledge.com/)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 09.16.2002 iluxa
+ * - first rough cut. basic MSP operations supported
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <asm/page.h>
+#include <linux/vmalloc.h> /* kmalloc() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h> /* O_ACCMODE */
+
+#include <asm/system.h> /* cli(), *_flags */
+#include <asm/pci.h>
+#include <asm/uaccess.h> /* put_user & friends */
+#include <asm/delay.h>
+
+/*
+ * The file operations for the msp device
+ * (some are overlayed with primary vice)
+ */
+
+#include <linux/vice.h>
+
+/* Statically allocate wait queue */
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+/*
+ * Loads MSP PC with value form msp->pc, takes msp out of reset
+ * state (just in case?) and kicks off execution.
+ */
+static inline void msp_go(vice_dev* vice)
+{
+ vice_write_reg(MSP_CTL_STAT,MSP_GO|MSP_OPERATIONAL);
+}
+
+static inline void vice_msp_stop(void)
+{
+ u64 ctl=vice_read_reg(MSP_CTL_STAT)&(~MSP_GO);
+ vice_write_reg(MSP_CTL_STAT,ctl);
+}
+
+int vice_msp_run(vice_dev *vice, msp_run* result)
+{
+ msp_run r;
+ if(!access_ok(VERIFY_WRITE,result,sizeof(msp_run)))
+ return -EFAULT;
+ DPRINTK("Checking for MSP status\n");
+ spin_lock_irq(vice->msp_lock);
+ if(vice->msp_status!=VICE_RES_STATUS_FREE) {
+ spin_unlock_irq(vice->msp_lock);
+ return -EBUSY;
+ }
+ DPRINTK("MSP is free\n");
+ vice->msp_status=VICE_RES_STATUS_INPROGRESS;
+ spin_unlock_irq(vice->msp_lock);
+ DPRINTK("Kicking MSP off\n");
+ msp_go(vice);
+ /*
+ * Sleep, untill MSP interrupts us...
+ *
+ * No spinlock is needed...
+ */
+ DPRINTK("Falling asleep\n");
+ while(vice->msp_status==VICE_RES_STATUS_INPROGRESS) {
+ interruptible_sleep_on(&wq);
+ DPRINTK("Huh? Where am I?\n");
+ if(signal_pending(current))break;
+ }
+ DPRINTK("*yawn* obviously waking up....\n");
+ copy_from_user(&r,result,sizeof(r));
+ DPRINTK("r.reason=%x, r.pc=%x, r.status=%x\n",r.reason,r.pc,r.status);
+ r.status=vice->msp_status;
+ vice->msp_status=VICE_RES_STATUS_FREE;
+ r.pc=vice->msp_pc;
+ r.reason=vice->msp_int_reason;
+ DPRINTK("r.reason=%x, r.pc=%x, r.status=%x\n",r.reason,r.pc,r.status);
+ return copy_to_user(result,&r,sizeof(r));
+}
+
+void vice_handle_msp_int(vice_dev* vice)
+{
+ DPRINTK("Ah! We are done with MSP!\n");
+ if(vice->msp_status!=VICE_RES_STATUS_INPROGRESS) {
+ DPRINTK("Ugh... MSP interrupt while MSP isn't started from driver!\n");
+ return;
+ }
+ vice->msp_status=VICE_RES_STATUS_DONE;
+ vice->msp_pc=-1; /* No exception, no EPC, and PC is probably
+ not one which executed Exception instruction */
+ vice->msp_int_reason=vice_read_reg(MSP_EXPT_FLAG);
+ wake_up_interruptible(&wq);
+}
+void vice_handle_msp_err(vice_dev* vice)
+{
+ DPRINTK("Ouch! MSP Exception!\n");
+ if(vice->msp_status!=VICE_RES_STATUS_INPROGRESS) {
+ DPRINTK("Ugh... MSP exception while MSP isn't started from driver!\n");
+ return;
+ }
+ vice->msp_status=VICE_RES_STATUS_ERR;
+ vice->msp_pc=(u32)vice_read_reg(MSP_EPC);
+ vice->msp_int_reason=vice_read_reg(MSP_EXPT_FLAG);
+ /* clear any exception bits */
+ vice_write_reg(MSP_EXPT_FLAG,0x00);
+ wake_up_interruptible(&wq);
+}
+
+int vice_msp_init(struct vice_dev* vice)
+{
+ spin_lock_init(&vice->dma_lock[0]);
+ return 0;
+}
+
+void vice_msp_reset(vice_dev *vice)
+{
+ /* start reset */
+ vice_write_reg(MSP_CTL_STAT,0);
+ /* wait for reset to complete */
+ udelay(1);
+ /* take out of reset, and prepare to go */
+ vice_write_reg(MSP_CTL_STAT,MSP_OPERATIONAL);
+ /* let MSP access all VICE internal RAM */
+ vice_write_reg(MSP_D_RAM,0x7);
+}
+
+void vice_msp_cleanup(vice_dev* vice)
+{
+ vice_msp_stop();
+}
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/Kconfig Sat Nov 2 14:10:16 2002
@@ -0,0 +1,32 @@
+#
+# O2 VICE Engine confiuration
+#
+
+config O2_VICE
+ tristate "O2 VICE Engine Support"
+ depends on SGI_IP32
+ ---help---
+ This option enables O2 VICE Engine support.
+ VICE stands for Video Image Compression Engine. This is very powerfull
+ piece of silicon, that can greatly speed up lots of graphics, vide, or
+ sound related tasks. To be able to use it, you will also need special
+ library, that can be found at <insert URL here>
+
+config O2_VICE_DBGG
+ bool "VICE Debugger Support. READ HELP!"
+ depends on O2_VICE
+ ---help---
+ This option enables features of VICE driver needed to debug VICE library.
+ This is probably serious security risk. You don't need it. If you think
+ you do, you are wrong. Say NO.
+
+config O2_VICE_DBG
+ bool "You seem to insist... did you read help? Yes? No? READ HELP!"
+ depends on O2_VICE_DBGG
+ ---help---
+ You are still here? Didn't I just tell you that it is not needed?
+ Or do you want to say you *legally* obtained information needed for
+ programming VICE? That you got all the tools needed? As a matter of
+ fact, these tools don't even exist yet!
+
+ Sigh... You've been warned...
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/Makefile Thu Sep 12 00:12:16 2002
@@ -0,0 +1,21 @@
+#
+# drivers/char/o2vice/Makefile
+#
+# Makefile for the O2 VICE Engine driver.
+#
+
+SUB_DIRS :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+#O_TARGET := vice.o
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_O2_VICE) += main.o msp.o bsp.o dma.o
+#obj-$(CONFIG_O2_VICE_DBG) += vicedebug.o
+
+include $(TOPDIR)/Rules.make
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/main.c Tue Dec 10 09:55:59 2002
@@ -0,0 +1,438 @@
+/*
+ * main.c -- SGI O2 VICE driver
+ *
+ * The code skeleton came from the book "Linux Device
+ * Drivers" by Alessandro Rubini and Jonathan Corbet, published
+ * by O'Reilly & Associates. No warranty is attached;
+ * we cannot take responsibility for errors or fitness for use.
+ *
+ * Copyright (C) 2002 Ilya Volynets.
+ * Sponsored by Total Knowledge
+ * http://www.total-knowledge.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *======================================================================
+ * 09.16.2002 iluxa
+ * - first rough cut is ready.
+ */
+
+/*
+ * When debugging support is turned off, there will be no access to most of
+ * VICE I/O space. No PIO access to ram and buffers for sure, as acceessing
+ * some of "unimplemented" regions seems to halt system completely. (Is CPU
+ * just stalling, waiting for data to be returned, instead of getting error?)
+ * Safe registers are first 4K (control registers?) and next 4K with DMA
+ * describtors.
+ * Well, I could give access to correct pages through "nopage" method...
+ * Then accessing "reserved" regions would give SIG_BUS...
+ * Data ram would be problem: there are 3 2K regions, which either makes
+ * only 2 banks accessible to userspace, or none at all (giving non-root user
+ * an option to randomly hang system is not an option :)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h> /* module_(init|exit) */
+
+#include <linux/kernel.h> /* printk() */
+#include <asm/page.h>
+#include <linux/vmalloc.h> /* kmalloc() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h> /* O_ACCMODE */
+
+#include <asm/system.h> /* cli(), *_flags */
+
+#include <linux/mm.h>
+
+#include <linux/vice.h> /* local definitions */
+
+#include <asm/ip32/ip32_ints.h>
+
+int vice_major = VICE_MAJOR;
+
+MODULE_PARM(vice_major, "i");
+MODULE_AUTHOR("Ilya Volynets");
+
+const char *vice_str="vice";
+
+/*
+ * Different minors behave differently, so let's use multiple fops
+ */
+
+
+void *vice_device; /* holds pointer to vice state (allocated in module_init) */
+
+/*
+ * vice_reset -- restes VICE engine
+ */
+int vice_reset(vice_dev * dev)
+{
+ vice_bsp_reset(dev);
+ vice_msp_reset(dev);
+ vice_dma_reset(dev);
+ return 0;
+}
+
+void vice_handle_buserr(vice_dev* vice)
+{
+ printk(KERN_WARNING "vice: received \"Erroneous data\" interrupt.\n");
+ printk(KERN_WARNING "\tUnfortunately I (Ilya Volynets) Have no idea what is it, so I'm simply ignoring it.\n");
+}
+
+static void vice_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
+{
+ struct vice_dev *vice = (struct vice_dev *) dev_id;
+ u64 status;
+ DPRINTK("irq!\n");
+ status=vice_read_reg(VICE_INT);
+
+ if (!vice /*paranoid */ ) {
+ DPRINTK ("Paranoja ouch!\n");
+ return;
+ }
+
+ DPRINTK("Interrupt, status %016lx...\n", status);
+ if (status & VICE_INT_DMA_CH1_DONE)
+ vice_dma_done(vice,0);
+ if (status & VICE_INT_DMA_CH1_ERR)
+ vice_dma_err(vice,0);
+ if (status & VICE_INT_DMA_CH2_DONE)
+ vice_dma_done(vice,1);
+ if (status & VICE_INT_DMA_CH2_ERR)
+ vice_dma_err(vice,1);
+ if (status & VICE_INT_MSP_SW)
+ vice_handle_msp_int(vice);
+ if (status & VICE_INT_MSP_ERR)
+ vice_handle_msp_err(vice);
+ if (status & VICE_INT_BSP_SW)
+ vice_handle_bsp_int(vice);
+ if (status & VICE_INT_BSP_ERR)
+ vice_handle_bsp_err(vice);
+ if (status & VICE_INT_BUSERR)
+ vice_handle_buserr(vice);
+
+ vice_write_reg(VICE_INT_RESET,0x1FF); /* clear handled interrupts */
+}
+
+/*
+ * Open and close
+ */
+
+/* In vice_open, the fop_array is used according to TYPE(dev) */
+int vice_open(struct inode *inode, struct file *filp)
+{
+ vice_dev *vice=vice_device; /* device information */
+ int res;
+
+ MOD_INC_USE_COUNT; /* Before we maybe sleep */
+
+ if(vice->is_open)
+ return -EBUSY;
+
+ if (!filp->private_data) {
+ filp->private_data = vice_device;
+ }
+
+ vice_reset(vice);
+
+ if ((res=request_irq(CRIME_VICE_IRQ, vice_interrupt, SA_SHIRQ, vice_str, vice))) {
+ printk(KERN_ERR "vice: Can't get irq %x: res=%i\n", (unsigned int)CRIME_VICE_INT, res);
+ return res;
+ }
+
+ /*Actual device init goes in here */
+
+ {
+ int ret;
+ if((ret=vice_dma_mem_init(vice))!=0) {
+ DPRINTK("Failure allocating VICE I/O buffers...\n");
+ vice_dma_mem_free(vice);
+ DPRINTK("Freed already-allocated memory...\n");
+ return ret;
+ }
+ /* enable interrupts in VICE */
+ vice_write_reg(VICE_INT_RESET,0x1FF); /* clear pending interrupts */
+ vice_write_reg(VICE_INT_EN,0x1FF);
+ }
+ vice->is_open=1;
+ return 0; /* success */
+}
+
+int vice_release(struct inode *inode, struct file *filp)
+{
+ vice_dev *vice=(vice_dev*)filp->private_data;
+
+ DPRINTK("closing down\n");
+ if(!vice->is_open) {
+ DPRINTK("Uuoouuuuch! Closing unopen file!!!!\n");
+ return -EINVAL; /*? Should I return something else? -ENOTOPEN? */
+ }
+ /* disable interrupts in VICE */
+ vice_write_reg(VICE_INT_EN,0x000);
+ free_irq(CRIME_VICE_IRQ, vice);
+ vice_dma_mem_free(vice);
+ vice_reset(vice);
+ vice->is_open=0;
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/*
+ * Data management: read and write
+ */
+
+ssize_t vice_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+ printk(KERN_WARNING
+ "Processing bit streams through reading/writing is not supported yet\n");
+ return -ENOSYS;
+}
+
+ssize_t vice_write(struct file * filp, const char *buf, size_t count,
+ loff_t * f_pos)
+{
+ printk(KERN_WARNING
+ "Processing bit streams through reading/writing is not supported (yet)\n");
+ return -ENOSYS;
+}
+
+/*
+ * The ioctl() implementation
+ */
+
+int vice_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ vice_dev *vice=(vice_dev*)filp->private_data;
+
+ switch(cmd) {
+ case VICE_IOCTL_MAP_DMA:
+ return vice_dma_map_set(vice,arg);
+ case VICE_IOCTL_MSP_RUN:
+ return vice_msp_run(vice,(msp_run*)arg);
+ case VICE_IOCTL_BSP_RUN:
+ return vice_bsp_run(vice,(bsp_run*)arg);
+ case VICE_IOCTL_DO_DMA:
+ return vice_dma_run(vice,(dma_run*)arg);
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+/*
+ * Common VMA ops.
+ */
+
+static void vice_vma_open(struct vm_area_struct *vma)
+{ MOD_INC_USE_COUNT; }
+
+static void vice_vma_close(struct vm_area_struct *vma)
+{ MOD_DEC_USE_COUNT; }
+/*
+ * All it does is find 4K page in one of 64K pages from vice->dev_mem
+ * There is no need to worry about I/O addresses here, since they are remap_page_ranged
+ * on initial mmap....
+ */
+struct page* vice_vma_nopage(struct vm_area_struct *vma,unsigned long address, int write)
+{
+ vice_dev *vice=(vice_dev*)vma->vm_private_data;
+ unsigned long fkpn=((address-vma->vm_start)>>PAGE_SHIFT)+
+ (vma->vm_pgoff-(VICE_MIN_OFFSET>>PAGE_SHIFT));
+ unsigned long v_pn=fkpn>>VICE_PAGE_ORDER;
+ unsigned long kaddr;
+ struct page *pgptr;
+ if(v_pn>=sizeof(vice->dma_mem)/sizeof(vice->dma_mem[0]))
+ return NOPAGE_SIGBUS;
+ kaddr=(unsigned long)KSEG0ADDR(vice->dma_kmem[v_pn])+((fkpn-(v_pn<<VICE_PAGE_ORDER))<<PAGE_SHIFT);
+ pgptr=virt_to_page(vice->dma_kmem[v_pn]);
+ get_page(pgptr);
+ return virt_to_page(kaddr);
+}
+
+static struct vm_operations_struct vice_vm_ops = {
+ open: vice_vma_open,
+ close: vice_vma_close,
+ nopage: vice_vma_nopage,
+};
+
+/*
+ * mmap I/O registers of VICE. Called when region is in 0-VICE_IO_MAX range.
+ */
+static inline int vice_io_mmap( struct vm_area_struct *vma)
+{
+ unsigned long offset=vma->vm_pgoff<<PAGE_SHIFT;
+ if(offset+vma->vm_end-vma->vm_start>VICE_IO_MAX_OFFSET+1) {
+ DPRINTK("invalid offset: %lu,length=%lx\n",offset,vma->vm_end-vma->vm_start);
+ return -EINVAL;
+ }
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO|VM_RESERVED;
+ flush_cache_all();
+ return remap_page_range(vma,vma->vm_start,VICE_BASE+offset,vma->vm_end-vma->vm_start,vma->vm_page_prot);
+}
+/*
+ * mmap I/O buffers. Called when region is above VICE_IO_MAX.
+ */
+
+static inline int vice_buffer_mmap( struct file* filep, struct vm_area_struct *vma)
+{
+ vice_dev *vice=(vice_dev*)filep->private_data;
+ unsigned long offset=vma->vm_pgoff<<PAGE_SHIFT;
+
+ /* must be VICE_PAGE aligned (64K) and size must be ... by 64K */
+ if (offset&0xFFFF||(vma->vm_end-vma->vm_start)&0xFFFF)
+ return -ENXIO; /* alignment error? */
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO|VM_RESERVED;
+
+ vma->vm_private_data=vice;
+ vma->vm_file = filep;
+ return 0;
+}
+
+static int vice_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long offset=vma->vm_pgoff<<PAGE_SHIFT;
+ vma->vm_ops = &vice_vm_ops;
+ if(offset<=VICE_IO_MAX_OFFSET)
+ return vice_io_mmap(vma);
+ else if(offset>=VICE_MIN_OFFSET&&offset+vma->vm_end-vma->vm_start<=VICE_MAX_OFFSET)
+ return vice_buffer_mmap(filp,vma);
+ else
+ return -EINVAL;
+ vice_vma_open(vma);
+}
+
+struct file_operations vice_fops = {
+ read:vice_read,
+ write:vice_write,
+ ioctl:vice_ioctl,
+ open:vice_open,
+ release:vice_release,
+ mmap:vice_mmap,
+};
+
+/*
+ * Finally, the module stuff
+ */
+
+#ifdef CONFIG_DEVFS_FS
+devfs_handle_t vice_devfs_dir;
+static char devname[4];
+#endif
+
+/*
+ * The cleanup function is used to handle initialization failures as well.
+ * Thefore, it must be careful to work correctly even if some of the items
+ * have not been initialized
+ */
+void vice_cleanup_module(void)
+{
+#ifndef CONFIG_DEVFS_FS
+ /* cleanup_module is never called if registering failed */
+ unregister_chrdev(vice_major, "vice");
+#endif
+
+ /* Cleanup MSP/BSP/DMA */
+ /* This really should be done in close.. */
+ vice_msp_cleanup(vice_device);
+ vice_bsp_cleanup(vice_device);
+ vice_dma_cleanup(vice_device);
+
+ /* Clean up DMA and other HW */
+
+ if (vice_device) {
+ kfree(vice_device);
+ }
+#ifdef CONFIG_DEVFS_FS
+ /* once again, only for devfs */
+ devfs_unregister(vice_devfs_dir);
+#endif
+}
+
+
+int vice_init_module(void)
+{
+ int result;
+ vice_dev *vice;
+
+ SET_MODULE_OWNER(&vice_fops);
+#ifdef CONFIG_DEVFS_FS
+ /* If we have devfs, create /dev/vice to put files in there */
+ vice_devfs_dir = devfs_mk_dir(NULL, "vice", NULL);
+ if (!vice_devfs_dir)
+ return -EBUSY; /* problem */
+
+#else /* no devfs, do it the "classic" way */
+
+ /*
+ * Register your major, and accept a dynamic number. This is the
+ * first thing to do, in order to avoid releasing other module's
+ * fops in vice_cleanup_module()
+ */
+ result = register_chrdev(vice_major, "vice", &vice_fops);
+ if (result < 0) {
+ printk(KERN_WARNING "vice: can't get major %d\n", vice_major);
+ return result;
+ }
+ if (vice_major == 0)
+ vice_major = result; /* dynamic */
+
+#endif /* CONFIG_DEVFS_FS */
+ /*
+ * allocate the devices -- we could have them static, but... I dunno...
+ */
+ vice = kmalloc(sizeof(vice_dev), GFP_KERNEL);
+ if (!vice) {
+ result = -ENOMEM;
+ goto fail;
+ }
+ vice_device = vice;
+ memset(vice, 0, sizeof(vice_dev));
+#ifdef CONFIG_DEVFS_FS
+ devfs_register(vice_devfs_dir, "vice",
+ DEVFS_FL_AUTO_DEVNUM,
+ 0, 0, S_IFCHR | S_IRUGO | S_IWUGO, &vice_fops, vice);
+#endif
+ if ((result = vice_dma_init(vice)))
+ goto fail;
+ /* Initialize MSP & BSP */
+ if ((result = vice_msp_init(vice)))
+ goto fail;
+ if ((result = vice_bsp_init(vice)))
+ goto fail;
+
+#ifndef VICE_DEBUG
+ EXPORT_NO_SYMBOLS; /* otherwise, leave global symbols visible */
+#endif
+
+ vice_write_reg(VICE_ID,0xfffff);
+#define ID_BITS 0xF
+ printk("SGI O2 VICE rev. %ld\n", vice_read_reg(VICE_ID)&ID_BITS);
+ return 0; /* succeed */
+
+ fail:
+ vice_cleanup_module();
+ return result;
+}
+
+module_init(vice_init_module);
+module_exit(vice_cleanup_module);
--- /dev/null Sun Jul 17 16:46:18 1994
+++ drivers/char/o2vice/dma.c Sat Nov 2 16:36:05 2002
@@ -0,0 +1,183 @@
+/*
+ *
+ * Copyright (C) 2002 Ilya Volynets
+ * Sponsored by Total Knowledge
+ * http://www.total-knowledge.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *======================================================================
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <asm/page.h>
+#include <linux/vmalloc.h> /* kmalloc() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/proc_fs.h>
+#include <linux/fcntl.h> /* O_ACCMODE */
+#include <linux/sched.h>
+
+#include <asm/system.h> /* cli(), *_flags */
+#include <asm/pci.h>
+#include <asm/uaccess.h> /* put_user & friends */
+#include <asm/delay.h>
+
+#include <asm/errno.h>
+#include <asm/addrspace.h>
+
+/*
+ * VICE DMA support
+ */
+
+#include <linux/vice.h>
+
+/* wait queue to sleep on, while waiting for DMA */
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+
+/*
+ * Maps one of 4M sets into VICE TLB.
+ * Currently set# can be either 0 or 1
+ */
+int vice_dma_map_set(vice_dev *vice,unsigned long set)
+{
+ unsigned long *page_set;
+ int i;
+ /* either map in 0th or 1st set (for now....) */
+ if(set>=2)
+ return -EINVAL;
+ page_set=&(vice->dma_mem[VICE_TLB_ENTRIES*set]);
+ for(i=0; i<VICE_TLB_ENTRIES; i++) {
+ vice_write_reg(VICE_TLB_OFFSET+(i<<3), page_set[i]|VICE_TLB_VALID|VICE_TLB_WRITABLE);
+ }
+ for(i=0; i<VICE_TLB_ENTRIES; i++) {
+ printk("%016lx ",vice_read_reg(VICE_TLB_OFFSET+(i<<3)));
+ }
+ printk("\n");
+ return 0;
+}
+
+/*
+ * Unmaps all pages from VICE TLB
+ */
+int vice_dma_clear_tlb(vice_dev *vice)
+{
+ int i;
+ for(i=0; i<VICE_TLB_ENTRIES; i++) {
+ vice_write_32(VICE_TLB_OFFSET+(i<<2), 0);
+ }
+ return 0;
+}
+
+int vice_dma_init(vice_dev* vice)
+{
+ int ret=0;
+ spin_lock_init(&vice->dma_lock[0]);
+ spin_lock_init(&vice->dma_lock[1]);
+ return ret;
+}
+
+int vice_dma_run(vice_dev* vice,dma_run* run)
+{
+ dma_run r;
+ if(copy_from_user(&r,run,sizeof(r)))
+ return -EINVAL;
+ if(r.channel>=2)
+ return -EINVAL;
+
+ /*
+ * Only reason I need this spinlock is if two threads are trying to
+ * _start_ DMA at the same time. All other accesses to dma_status need not
+ * be interlocked.
+ */
+ DPRINTK("Checking for channel status\n");
+ spin_lock_irq(vice->dma_lock[r.channel]);
+ if(vice->dma_status[r.channel]!=VICE_RES_STATUS_FREE) {
+ spin_unlock_irq(vice->dma_lock[r.channel]);
+ return -EBUSY;
+ }
+ DPRINTK("Channel OK\n");
+ vice->dma_status[r.channel]=VICE_RES_STATUS_INPROGRESS;
+ spin_unlock_irq(vice->dma_lock[r.channel]);
+ DPRINTK("Kicking DMA off\n");
+ if(r.channel==0)
+ vice_write_reg(DMA_CH1_CTL,r.desc|VICE_DMA_CTL_GO|VICE_DMA_CTL_IE);
+ else
+ vice_write_reg(DMA_CH2_CTL,r.desc|VICE_DMA_CTL_GO|VICE_DMA_CTL_IE);
+ /*
+ * Sleep, untill this channel sends DMA_DONE or DMA_ERR interrupt...
+ *
+ * No spinlock is needed...
+ */
+ DPRINTK("Falling asleep\n");
+ while(vice->dma_status[r.channel]==VICE_RES_STATUS_INPROGRESS) {
+ interruptible_sleep_on(&wq);
+ DPRINTK("Huh? Where am I?\n");
+ if(signal_pending(current))break;
+ }
+ DPRINTK("*yawn* obviously waking up....\n");
+ r.status=vice->dma_status[r.channel];
+ vice->dma_status[r.channel]=VICE_RES_STATUS_FREE;
+ __copy_to_user(&r,run,sizeof(r));
+ DPRINTK("Done\n");
+ return 0;
+}
+
+void vice_dma_done(vice_dev *vice, int channel)
+{
+ DPRINTK("DMA done\n");
+
+ if(vice->dma_status[channel]!=VICE_RES_STATUS_INPROGRESS) {
+ DPRINTK("Ugh... DMA interrupt on channel %d, while DMA on that channel isn't initiated from CPU!\n",channel);
+ return;
+ }
+ vice->dma_status[channel]=VICE_RES_STATUS_DONE;
+ wake_up_interruptible(&wq);
+}
+
+void vice_dma_err(vice_dev *vice, int channel)
+{
+ DPRINTK("DMA error\n");
+ spin_lock_irq(vice->dma_lock[channel]);
+ vice->dma_status[channel]=VICE_RES_STATUS_ERR;
+ spin_unlock_irq(vice->dma_lock[channel]);
+ wake_up_interruptible(&wq);
+}
+
+/*
+ * Need to stop all DMA transfers
+ */
+
+void vice_dma_cleanup(vice_dev* vice)
+{
+}
+
+void vice_dma_reset(vice_dev* vice)
+{
+ /*
+ * Is DMA engine resettable?
+ * ... Yes, which register?
+ */
+ vice_write_reg(DMA_CH1_CTL,VICE_DMA_CTL_RESET);
+ vice_write_reg(DMA_CH2_CTL,VICE_DMA_CTL_RESET);
+ udelay(16); /* sleep for at least 16 VICE clocks */
+ vice_write_reg(DMA_CH1_CTL,VICE_DMA_CTL_IE|VICE_DMA_CTL_DESC1);
+ vice_write_reg(DMA_CH2_CTL,VICE_DMA_CTL_IE|VICE_DMA_CTL_DESC1);
+ vice_dma_clear_tlb(vice);
+}
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: O2 VICE support
2002-12-10 19:11 O2 VICE support ilya
@ 2002-12-11 13:38 ` Christoph Hellwig
2002-12-11 22:16 ` ilya
2002-12-22 9:20 ` Geert Uytterhoeven
1 sibling, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2002-12-11 13:38 UTC (permalink / raw)
To: ilya; +Cc: linux-mips, ralf
On Tue, Dec 10, 2002 at 11:11:20AM -0800, ilya@theIlya.com wrote:
> RCS file: /home/cvs/linux/arch/mips64/kernel/ioctl32.c,v
> retrieving revision 1.26
> diff -u -r1.26 ioctl32.c
> --- arch/mips64/kernel/ioctl32.c 12 Nov 2002 15:26:11 -0000 1.26
> +++ arch/mips64/kernel/ioctl32.c 10 Dec 2002 17:02:29 -0000
> @@ -55,6 +57,10 @@
>
> #include <linux/rtc.h>
>
> +#ifdef CONFIG_O2_VICE
> +#include <linux/vice.h>
> +#endif
Just include the header unconditionally.
> static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
> @@ -827,6 +968,12 @@
> COMPATIBLE_IOCTL(TIOCGSERIAL)
> COMPATIBLE_IOCTL(TIOCSSERIAL)
> COMPATIBLE_IOCTL(TIOCSERGETLSR)
> +#ifdef CONFIG_O2_VICE
> +COMPATIBLE_IOCTL(VICE_IOCTL_MAP_DMA)
> +COMPATIBLE_IOCTL(VICE_IOCTL_MSP_RUN)
> +COMPATIBLE_IOCTL(VICE_IOCTL_BSP_RUN)
> +COMPATIBLE_IOCTL(VICE_IOCTL_DO_DMA)
> +#endif
Dito. COMPATIBLE_IOCTL() isn't a big burgden, so it doesn't harm to get
rid of the ifdefs.
> +source drivers/char/o2vice/Kconfig
I think it should be in drivers/media/vice (i.e. it's one of the media
devices, and I don't think you need the o2, especially as you don't
use it e.g. in the header name).
> --- /dev/null Sun Jul 17 16:46:18 1994
> +++ drivers/char/o2vice/Makefile Thu Sep 12 00:12:16 2002
> @@ -0,0 +1,21 @@
> +#
> +# drivers/char/o2vice/Makefile
> +#
> +# Makefile for the O2 VICE Engine driver.
> +#
> +
> +SUB_DIRS :=
> +MOD_SUB_DIRS := $(SUB_DIRS)
> +ALL_SUB_DIRS := $(SUB_DIRS)
> +
> +#O_TARGET := vice.o
> +
> +obj-y :=
> +obj-m :=
> +obj-n :=
> +obj- :=
This is 2.2 crap. Just get rid of it..
> +
> +obj-$(CONFIG_O2_VICE) += main.o msp.o bsp.o dma.o
> +#obj-$(CONFIG_O2_VICE_DBG) += vicedebug.o
> +
> +include $(TOPDIR)/Rules.make
The include isn't needed anymore either in 2.5.
> +#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
> +#ifdef __KERNEL__
> +#include <asm/pci.h>
> +#endif
> +#include <linux/types.h> /* size_t */
> +
> +#ifndef __KERNEL__
> +typedef __u64 u64;
> +typedef __u32 u32;
> +typedef __u16 u16;
> +#endif /* __KERNEL */
Urgg. Usually kernel headers aren't supposed to be used in userspace.
If you want to use a copy anyway it should be done with much less burden
on the kernel code.
> +#ifdef VICE_DEBUG
> +# define DPRINTK(fmt, args...) printk( KERN_DEBUG "vice: " fmt, ## args)
> +#else
> +# define DPRINTK(fmt, args...) /* not debugging: nothing */
> +#endif
> +
> +#define PDEBUG DPRINTK
Just use pr_debug?
> +
> +#ifndef VICE_MAJOR
> +#define VICE_MAJOR 240 /* dynamic major by default */
> +#endif
Comment doesn't match code.
> +/*
> + * Prototypes for shared functions
> + */
> +ssize_t vice_read (struct file *filp, char *buf, size_t count,
> + loff_t *f_pos);
> +ssize_t vice_write (struct file *filp, const char *buf, size_t count,
> + loff_t *f_pos);
> +loff_t vice_llseek (struct file *filp, loff_t off, int whence);
> +int vice_ioctl (struct inode *inode, struct file *filp,
> + unsigned int cmd, unsigned long arg);
Exported file operations are usually a very bad sign. But it looks like
you could just make them static anyway :)
> +/*
> + * VICE ioctl commands
> + */
> +#ifdef __KERNEL__
> +#define VICE_IOCTL_MAGIC 0x96
> +#define VICE_IOCTL_MAP_DMA _IOR(VICE_IOCTL_MAGIC,1,unsigned long)
> +#define VICE_IOCTL_MSP_RUN _IOR(VICE_IOCTL_MAGIC,2,msp_run)
> +#define VICE_IOCTL_BSP_RUN _IOR(VICE_IOCTL_MAGIC,3,bsp_run)
> +#define VICE_IOCTL_DO_DMA _IOWR(VICE_IOCTL_MAGIC,4,dma_run)
> +#else
> +#define VICE_IOCTL_MAP_DMA 0x40089601
> +#define VICE_IOCTL_MSP_RUN 0x400c9602
> +#define VICE_IOCTL_BSP_RUN 0x400c9603
> +#define VICE_IOCTL_DO_DMA 0xc00c9604
> +#endif
Ummm..
> +static inline int vice_dma_mem_init(vice_dev *vice)
> +{
> + int i;
> + for (i=0; i<64*2;i++){
> + if(!(vice->dma_kmem[i]=pci_alloc_consistent(0,VICE_PAGE_SIZE,&(vice->dma_mem[i])))) {
> + DPRINTK("failed at page# %i\n",i);
> + return -ENOMEM;
> + }
> + }
> + return 0;
Please adopt to Documentation/CodingStyle
> + DPRINTK("Falling asleep\n");
> + while(vice->msp_status==VICE_RES_STATUS_INPROGRESS) {
> + interruptible_sleep_on(&wq);
sleep_on is racy. You should at least use wait_even, but it doesn't look
like vice->msp_status is atomically updated anyway.
> --- /dev/null Sun Jul 17 16:46:18 1994
> +++ drivers/char/o2vice/Makefile Thu Sep 12 00:12:16 2002
The diff seems to include the same hunk twice..
> +/* In vice_open, the fop_array is used according to TYPE(dev) */
> +int vice_open(struct inode *inode, struct file *filp)
> +{
> + vice_dev *vice=vice_device; /* device information */
> + int res;
> +
> + MOD_INC_USE_COUNT; /* Before we maybe sleep */
Please set .owner in the file_operations instead.
> +
> + if(vice->is_open)
> + return -EBUSY;
This seems pretty racy.
> +
> + if (!filp->private_data) {
> + filp->private_data = vice_device;
> + }
filp->private_data can't be set.
> +ssize_t vice_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
> +{
> + printk(KERN_WARNING
> + "Processing bit streams through reading/writing is not supported yet\n");
> + return -ENOSYS;
> +}
> +
> +ssize_t vice_write(struct file * filp, const char *buf, size_t count,
> + loff_t * f_pos)
> +{
> + printk(KERN_WARNING
> + "Processing bit streams through reading/writing is not supported (yet)\n");
> + return -ENOSYS;
> +}
What about just not implementing the methods instead?
> +static void vice_vma_open(struct vm_area_struct *vma)
> +{ MOD_INC_USE_COUNT; }
> +
> +static void vice_vma_close(struct vm_area_struct *vma)
> +{ MOD_DEC_USE_COUNT; }
This is silly. You get a reference for vma->vm_file as long as you
have any mmaps. That's enough for the refcounting.
> +static struct vm_operations_struct vice_vm_ops = {
> + open: vice_vma_open,
> + close: vice_vma_close,
> + nopage: vice_vma_nopage,
> +};
Please use C99-initializers (i.e. .foo = bar)
> +void vice_cleanup_module(void)
> +{
> +#ifndef CONFIG_DEVFS_FS
> + /* cleanup_module is never called if registering failed */
> + unregister_chrdev(vice_major, "vice");
> +#endif
Umm, just because someone makes the mistake of enabling devfs he
doesn't have to use it.. :)
> +#ifndef VICE_DEBUG
> + EXPORT_NO_SYMBOLS; /* otherwise, leave global symbols visible */
> +#endif
EXPORT_NO_SYMBOLS is a noop on 2.5
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: O2 VICE support
2002-12-11 13:38 ` Christoph Hellwig
@ 2002-12-11 22:16 ` ilya
2002-12-11 22:45 ` Christoph Hellwig
2002-12-11 22:46 ` Juan Quintela
0 siblings, 2 replies; 6+ messages in thread
From: ilya @ 2002-12-11 22:16 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-mips, ralf
[-- Attachment #1: Type: text/plain, Size: 2613 bytes --]
> Urgg. Usually kernel headers aren't supposed to be used in userspace.
> If you want to use a copy anyway it should be done with much less burden
> on the kernel code.
Well, most of manipulation of this device will be done bu user-space
code. Kernel's only job is synchronising access and managing memory.
Thus we would like to keep all definitions in one place.
> > + if (!filp->private_data) {
> > + filp->private_data = vice_device;
> > + }
>
> filp->private_data can't be set.
???
I can live without using it of course, since it isn't currently possible to have
more then one instance of VICE in same machine, but theoretical possibility does
exist. Where should I pass information about which specific device current
call is?
>
> > +ssize_t vice_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
> > +{
> > + printk(KERN_WARNING
> > + "Processing bit streams through reading/writing is not supported yet\n");
> > + return -ENOSYS;
> > +}
> > +
> > +ssize_t vice_write(struct file * filp, const char *buf, size_t count,
> > + loff_t * f_pos)
> > +{
> > + printk(KERN_WARNING
> > + "Processing bit streams through reading/writing is not supported (yet)\n");
> > + return -ENOSYS;
> > +}
>
> What about just not implementing the methods instead?
This is more like reminder to myself that I should do that one day :)
> > +static void vice_vma_open(struct vm_area_struct *vma)
> > +{ MOD_INC_USE_COUNT; }
> > +
> > +static void vice_vma_close(struct vm_area_struct *vma)
> > +{ MOD_DEC_USE_COUNT; }
>
> This is silly. You get a reference for vma->vm_file as long as you
> have any mmaps. That's enough for the refcounting.
I was wondering about that too, but this is the way i was in book :)
>
> > +static struct vm_operations_struct vice_vm_ops = {
> > + open: vice_vma_open,
> > + close: vice_vma_close,
> > + nopage: vice_vma_nopage,
> > +};
>
> Please use C99-initializers (i.e. .foo = bar)
>
> > +void vice_cleanup_module(void)
> > +{
> > +#ifndef CONFIG_DEVFS_FS
> > + /* cleanup_module is never called if registering failed */
> > + unregister_chrdev(vice_major, "vice");
> > +#endif
>
> Umm, just because someone makes the mistake of enabling devfs he
> doesn't have to use it.. :)
I'm not buying that one :)
>
> > +#ifndef VICE_DEBUG
> > + EXPORT_NO_SYMBOLS; /* otherwise, leave global symbols visible */
> > +#endif
>
> EXPORT_NO_SYMBOLS is a noop on 2.5
Driver was written for 2.4 first.
Thanks a lot for constructive criticism.
Ilya.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: O2 VICE support
2002-12-11 22:16 ` ilya
@ 2002-12-11 22:45 ` Christoph Hellwig
2002-12-11 22:46 ` Juan Quintela
1 sibling, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2002-12-11 22:45 UTC (permalink / raw)
To: ilya; +Cc: linux-mips, ralf
On Wed, Dec 11, 2002 at 02:16:29PM -0800, ilya@theIlya.com wrote:
> > > + if (!filp->private_data) {
> > > + filp->private_data = vice_device;
> > > + }
> >
> > filp->private_data can't be set.
> ???
> I can live without using it of course, since it isn't currently possible to have
> more then one instance of VICE in same machine, but theoretical possibility does
> exist. Where should I pass information about which specific device current
> call is?
Sorry if that sentence was confusing. I meant it can't be already set in
->open so the if is superflous.
> > > +void vice_cleanup_module(void)
> > > +{
> > > +#ifndef CONFIG_DEVFS_FS
> > > + /* cleanup_module is never called if registering failed */
> > > + unregister_chrdev(vice_major, "vice");
> > > +#endif
> >
> > Umm, just because someone makes the mistake of enabling devfs he
> > doesn't have to use it.. :)
> I'm not buying that one :)
You can have CONFIG_DEVFS_FS set but devfs not mounted and used.
Thus #ifndef CONFIG_DEVFS_FS code is a very bad idea.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: O2 VICE support
2002-12-11 22:16 ` ilya
2002-12-11 22:45 ` Christoph Hellwig
@ 2002-12-11 22:46 ` Juan Quintela
1 sibling, 0 replies; 6+ messages in thread
From: Juan Quintela @ 2002-12-11 22:46 UTC (permalink / raw)
To: ilya; +Cc: Christoph Hellwig, linux-mips, ralf
>>>>> "ilya" == ilya <ilya@theIlya.com> writes:
>>
>> > +void vice_cleanup_module(void)
>> > +{
>> > +#ifndef CONFIG_DEVFS_FS
>> > + /* cleanup_module is never called if registering failed */
>> > + unregister_chrdev(vice_major, "vice");
>> > +#endif
>>
>> Umm, just because someone makes the mistake of enabling devfs he
>> doesn't have to use it.. :)
ilya> I'm not buying that one :)
Read behind the joke:
- you have devfs compiled in
- you don't have devfs mounted
Conclusion:
there is a bug in your code :)
Later, Juan.
--
In theory, practice and theory are the same, but in practice they
are different -- Larry McVoy
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: O2 VICE support
2002-12-10 19:11 O2 VICE support ilya
2002-12-11 13:38 ` Christoph Hellwig
@ 2002-12-22 9:20 ` Geert Uytterhoeven
1 sibling, 0 replies; 6+ messages in thread
From: Geert Uytterhoeven @ 2002-12-22 9:20 UTC (permalink / raw)
To: ilya; +Cc: Linux/MIPS Development, Ralf Baechle
On Tue, 10 Dec 2002 ilya@theIlya.com wrote:
> Attached is patch set to add support to kernel for O2 video compression engine
> (VICE). It should apply cleanly to latest CVS.
> +config O2_VICE
> + tristate "O2 VICE Engine Support"
> + depends on SGI_IP32
> + ---help---
> + This option enables O2 VICE Engine support.
> + VICE stands for Video Image Compression Engine. This is very powerfull
> + piece of silicon, that can greatly speed up lots of graphics, vide, or
> + sound related tasks. To be able to use it, you will also need special
> + library, that can be found at <insert URL here>
^^^^^^^^^^^^^^^^^
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2002-12-23 11:36 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-10 19:11 O2 VICE support ilya
2002-12-11 13:38 ` Christoph Hellwig
2002-12-11 22:16 ` ilya
2002-12-11 22:45 ` Christoph Hellwig
2002-12-11 22:46 ` Juan Quintela
2002-12-22 9:20 ` Geert Uytterhoeven
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.