/*
* mm.c - Micro Memory(tm) PCI memory board block device driver - v2.3
*
* (C) 2001 San Mehat <nettwerk@valinux.com>
* (C) 2001 Johannes Erdfelt <jerdfelt@valinux.com>
* (C) 2001 NeilBrown <neilb@cse.unsw.edu.au>
*
* This driver for the Micro Memory PCI Memory Module with Battery Backup
* is Copyright Micro Memory Inc 2001-2002. All rights reserved.
*
* This driver is released to the public under the terms of the
* GNU GENERAL PUBLIC LICENSE version 2
* See the file COPYING for details.
*
* This driver provides a standard block device interface for Micro Memory(tm)
* PCI based RAM boards.
* 10/05/01: Phap Nguyen - Rebuilt the driver
* 10/22/01: Phap Nguyen - v2.1 Added disk partitioning
* 29oct2001:NeilBrown - Use make_request_fn instead of request_fn
* - use stand disk partitioning (so fdisk works).
* 08nov2001:NeilBrown - change driver name from "mm" to "umem"
* - incorporate into main kernel
* 08apr2002:NeilBrown - Move some of interrupt handle to tasklet
* - use spin_lock_bh instead of _irq
* - Never block on make_request. queue
* bh's instead.
* - unregister umem from devfs at mod unload
* - Change version to 2.3
* 07Nov2001:Phap Nguyen - Select pci read command: 06, 12, 15 (Decimal)
* 07Jan2002: P. Nguyen - Used PCI Memory Write & Invalidate for DMA
* 15May2002:NeilBrown - convert to bio for 2.5
* 17May2002:NeilBrown - remove init_mem initialisation. Instead detect
* - a sequence of writes that cover the card, and
* - set initialised bit then.
*/
//#define DEBUG /* uncomment if you want debugging info (pr_debug) */
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/ioctl.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/umem.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define MM_MAXCARDS 4
#define MM_RAHEAD 2 /* two sectors */
#define MM_BLKSIZE 1024 /* 1k blocks */
#define MM_HARDSECT 512 /* 512-byte hardware sectors */
#define MM_SHIFT 6 /* max 64 partitions on 4 cards */
/*
* Version Information
*/
#define DRIVER_VERSION "v2.3"
#define DRIVER_AUTHOR "San Mehat, Johannes Erdfelt, NeilBrown"
#define DRIVER_DESC "Micro Memory(tm) PCI memory board block driver"
static int debug;
/* #define HW_TRACE(x) writeb(x,cards[0].csr_remap + MEMCTRLSTATUS_MAGIC) */
#define HW_TRACE(x)
#define DEBUG_LED_ON_TRANSFER 0x01
#define DEBUG_BATTERY_POLLING 0x02
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug bitmask");
static int pci_read_cmd = 0x0C; /* Read Multiple */
module_param(pci_read_cmd, int, 0);
MODULE_PARM_DESC(pci_read_cmd, "PCI read command");
static int pci_write_cmd = 0x0F; /* Write and Invalidate */
module_param(pci_write_cmd, int, 0);
MODULE_PARM_DESC(pci_write_cmd, "PCI write command");
static int pci_cmds;
static int major_nr;
#include <linux/blkdev.h>
#include <linux/blkpg.h>
struct cardinfo {
int card_number;
struct pci_dev *dev;
int irq;
unsigned long csr_base;
unsigned char __iomem *csr_remap;
unsigned long csr_len;
#ifdef CONFIG_MM_MAP_MEMORY
unsigned long mem_base;
unsigned char __iomem *mem_remap;
unsigned long mem_len;
#endif
unsigned int win_size; /* PCI window size */
unsigned int mm_size; /* size in kbytes */
unsigned int init_size; /* initial segment, in sectors,
* that we know to
* have been written
*/
struct bio *bio, *currentbio, **biotail;
request_queue_t *queue;
struct mm_page {
dma_addr_t page_dma;
struct mm_dma_desc *desc;
int cnt, headcnt;
struct bio *bio, **biotail;
} mm_pages[2];
#define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc))
int Active, Ready;
struct tasklet_struct tasklet;
unsigned int dma_status;
struct {
int good