|
|
|
@ -34,7 +34,7 @@
|
|
|
|
|
* - set initialised bit then.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//#define DEBUG /* uncomment if you want debugging info (pr_debug) */
|
|
|
|
|
#undef DEBUG /* #define DEBUG if you want debugging info (pr_debug) */
|
|
|
|
|
#include <linux/fs.h>
|
|
|
|
|
#include <linux/bio.h>
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
@ -143,17 +143,12 @@ static struct cardinfo cards[MM_MAXCARDS];
|
|
|
|
|
static struct block_device_operations mm_fops;
|
|
|
|
|
static struct timer_list battery_timer;
|
|
|
|
|
|
|
|
|
|
static int num_cards = 0;
|
|
|
|
|
static int num_cards;
|
|
|
|
|
|
|
|
|
|
static struct gendisk *mm_gendisk[MM_MAXCARDS];
|
|
|
|
|
|
|
|
|
|
static void check_batteries(struct cardinfo *card);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- get_userbit
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static int get_userbit(struct cardinfo *card, int bit)
|
|
|
|
|
{
|
|
|
|
|
unsigned char led;
|
|
|
|
@ -161,11 +156,7 @@ static int get_userbit(struct cardinfo *card, int bit)
|
|
|
|
|
led = readb(card->csr_remap + MEMCTRLCMD_LEDCTRL);
|
|
|
|
|
return led & bit;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- set_userbit
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int set_userbit(struct cardinfo *card, int bit, unsigned char state)
|
|
|
|
|
{
|
|
|
|
|
unsigned char led;
|
|
|
|
@ -179,11 +170,7 @@ static int set_userbit(struct cardinfo *card, int bit, unsigned char state)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- set_led
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* NOTE: For the power LED, use the LED_POWER_* macros since they differ
|
|
|
|
|
*/
|
|
|
|
@ -203,11 +190,6 @@ static void set_led(struct cardinfo *card, int shift, unsigned char state)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef MM_DIAG
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- dump_regs
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static void dump_regs(struct cardinfo *card)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *p;
|
|
|
|
@ -224,32 +206,28 @@ static void dump_regs(struct cardinfo *card)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- dump_dmastat
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void dump_dmastat(struct cardinfo *card, unsigned int dmastat)
|
|
|
|
|
{
|
|
|
|
|
dev_printk(KERN_DEBUG, &card->dev->dev, "DMAstat - ");
|
|
|
|
|
if (dmastat & DMASCR_ANY_ERR)
|
|
|
|
|
printk("ANY_ERR ");
|
|
|
|
|
printk(KERN_CONT "ANY_ERR ");
|
|
|
|
|
if (dmastat & DMASCR_MBE_ERR)
|
|
|
|
|
printk("MBE_ERR ");
|
|
|
|
|
printk(KERN_CONT "MBE_ERR ");
|
|
|
|
|
if (dmastat & DMASCR_PARITY_ERR_REP)
|
|
|
|
|
printk("PARITY_ERR_REP ");
|
|
|
|
|
printk(KERN_CONT "PARITY_ERR_REP ");
|
|
|
|
|
if (dmastat & DMASCR_PARITY_ERR_DET)
|
|
|
|
|
printk("PARITY_ERR_DET ");
|
|
|
|
|
printk(KERN_CONT "PARITY_ERR_DET ");
|
|
|
|
|
if (dmastat & DMASCR_SYSTEM_ERR_SIG)
|
|
|
|
|
printk("SYSTEM_ERR_SIG ");
|
|
|
|
|
printk(KERN_CONT "SYSTEM_ERR_SIG ");
|
|
|
|
|
if (dmastat & DMASCR_TARGET_ABT)
|
|
|
|
|
printk("TARGET_ABT ");
|
|
|
|
|
printk(KERN_CONT "TARGET_ABT ");
|
|
|
|
|
if (dmastat & DMASCR_MASTER_ABT)
|
|
|
|
|
printk("MASTER_ABT ");
|
|
|
|
|
printk(KERN_CONT "MASTER_ABT ");
|
|
|
|
|
if (dmastat & DMASCR_CHAIN_COMPLETE)
|
|
|
|
|
printk("CHAIN_COMPLETE ");
|
|
|
|
|
printk(KERN_CONT "CHAIN_COMPLETE ");
|
|
|
|
|
if (dmastat & DMASCR_DMA_COMPLETE)
|
|
|
|
|
printk("DMA_COMPLETE ");
|
|
|
|
|
printk(KERN_CONT "DMA_COMPLETE ");
|
|
|
|
|
printk("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -286,7 +264,8 @@ static void mm_start_io(struct cardinfo *card)
|
|
|
|
|
|
|
|
|
|
/* make the last descriptor end the chain */
|
|
|
|
|
page = &card->mm_pages[card->Active];
|
|
|
|
|
pr_debug("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
|
|
|
|
|
pr_debug("start_io: %d %d->%d\n",
|
|
|
|
|
card->Active, page->headcnt, page->cnt - 1);
|
|
|
|
|
desc = &page->desc[page->cnt-1];
|
|
|
|
|
|
|
|
|
|
desc->control_bits |= cpu_to_le32(DMASCR_CHAIN_COMP_EN);
|
|
|
|
@ -455,8 +434,8 @@ static void process_page(unsigned long data)
|
|
|
|
|
/* check if any of the requests in the page are DMA_COMPLETE,
|
|
|
|
|
* and deal with them appropriately.
|
|
|
|
|
* If we find a descriptor without DMA_COMPLETE in the semaphore, then
|
|
|
|
|
* dma must have hit an error on that descriptor, so use dma_status instead
|
|
|
|
|
* and assume that all following descriptors must be re-tried.
|
|
|
|
|
* dma must have hit an error on that descriptor, so use dma_status
|
|
|
|
|
* instead and assume that all following descriptors must be re-tried.
|
|
|
|
|
*/
|
|
|
|
|
struct mm_page *page;
|
|
|
|
|
struct bio *return_bio = NULL;
|
|
|
|
@ -501,7 +480,8 @@ static void process_page(unsigned long data)
|
|
|
|
|
le32_to_cpu(desc->transfer_size));
|
|
|
|
|
dump_dmastat(card, control);
|
|
|
|
|
} else if (test_bit(BIO_RW, &bio->bi_rw) &&
|
|
|
|
|
le32_to_cpu(desc->local_addr)>>9 == card->init_size) {
|
|
|
|
|
le32_to_cpu(desc->local_addr) >> 9 ==
|
|
|
|
|
card->init_size) {
|
|
|
|
|
card->init_size += le32_to_cpu(desc->transfer_size) >> 9;
|
|
|
|
|
if (card->init_size >> 1 >= card->mm_size) {
|
|
|
|
|
dev_printk(KERN_INFO, &card->dev->dev,
|
|
|
|
@ -514,7 +494,8 @@ static void process_page(unsigned long data)
|
|
|
|
|
return_bio = bio;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (last) break;
|
|
|
|
|
if (last)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debug & DEBUG_LED_ON_TRANSFER)
|
|
|
|
@ -545,11 +526,6 @@ static void process_page(unsigned long data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_make_request
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static int mm_make_request(struct request_queue *q, struct bio *bio)
|
|
|
|
|
{
|
|
|
|
|
struct cardinfo *card = q->queuedata;
|
|
|
|
@ -566,11 +542,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_interrupt
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static irqreturn_t mm_interrupt(int irq, void *__card)
|
|
|
|
|
{
|
|
|
|
|
struct cardinfo *card = (struct cardinfo *) __card;
|
|
|
|
@ -602,9 +573,12 @@ HW_TRACE(0x30);
|
|
|
|
|
|
|
|
|
|
stat = readb(card->csr_remap + MEMCTRLCMD_ERRSTATUS);
|
|
|
|
|
|
|
|
|
|
data_log1 = le32_to_cpu(readl(card->csr_remap + ERROR_DATA_LOG));
|
|
|
|
|
data_log2 = le32_to_cpu(readl(card->csr_remap + ERROR_DATA_LOG + 4));
|
|
|
|
|
addr_log1 = le32_to_cpu(readl(card->csr_remap + ERROR_ADDR_LOG));
|
|
|
|
|
data_log1 = le32_to_cpu(readl(card->csr_remap +
|
|
|
|
|
ERROR_DATA_LOG));
|
|
|
|
|
data_log2 = le32_to_cpu(readl(card->csr_remap +
|
|
|
|
|
ERROR_DATA_LOG + 4));
|
|
|
|
|
addr_log1 = le32_to_cpu(readl(card->csr_remap +
|
|
|
|
|
ERROR_ADDR_LOG));
|
|
|
|
|
addr_log2 = readb(card->csr_remap + ERROR_ADDR_LOG + 4);
|
|
|
|
|
|
|
|
|
|
count = readb(card->csr_remap + ERROR_COUNT);
|
|
|
|
@ -671,11 +645,7 @@ HW_TRACE(0x36);
|
|
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- set_fault_to_battery_status
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If both batteries are good, no LED
|
|
|
|
|
* If either battery has been warned, solid LED
|
|
|
|
@ -696,12 +666,6 @@ static void set_fault_to_battery_status(struct cardinfo *card)
|
|
|
|
|
|
|
|
|
|
static void init_battery_timer(void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- check_battery
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static int check_battery(struct cardinfo *card, int battery, int status)
|
|
|
|
|
{
|
|
|
|
|
if (status != card->battery[battery].good) {
|
|
|
|
@ -730,11 +694,7 @@ static int check_battery(struct cardinfo *card, int battery, int status)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- check_batteries
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void check_batteries(struct cardinfo *card)
|
|
|
|
|
{
|
|
|
|
|
/* NOTE: this must *never* be called while the card
|
|
|
|
@ -775,11 +735,7 @@ static void check_all_batteries(unsigned long ptr)
|
|
|
|
|
|
|
|
|
|
init_battery_timer();
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- init_battery_timer
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void init_battery_timer(void)
|
|
|
|
|
{
|
|
|
|
|
init_timer(&battery_timer);
|
|
|
|
@ -787,20 +743,12 @@ static void init_battery_timer(void)
|
|
|
|
|
battery_timer.expires = jiffies + (HZ * 60);
|
|
|
|
|
add_timer(&battery_timer);
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- del_battery_timer
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void del_battery_timer(void)
|
|
|
|
|
{
|
|
|
|
|
del_timer(&battery_timer);
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_revalidate
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Note no locks taken out here. In a worst case scenario, we could drop
|
|
|
|
|
* a chunk of system memory. But that should never happen, since validation
|
|
|
|
@ -833,33 +781,23 @@ static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_check_change
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
Future support for removable devices
|
|
|
|
|
* Future support for removable devices
|
|
|
|
|
*/
|
|
|
|
|
static int mm_check_change(struct gendisk *disk)
|
|
|
|
|
{
|
|
|
|
|
/* struct cardinfo *dev = disk->private_data; */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_fops
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static struct block_device_operations mm_fops = {
|
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
|
.getgeo = mm_getgeo,
|
|
|
|
|
.revalidate_disk = mm_revalidate,
|
|
|
|
|
.media_changed = mm_check_change,
|
|
|
|
|
};
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_pci_probe
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
|
|
|
|
|
|
|
|
static int __devinit mm_pci_probe(struct pci_dev *dev,
|
|
|
|
|
const struct pci_device_id *id)
|
|
|
|
|
{
|
|
|
|
|
int ret = -ENODEV;
|
|
|
|
|
struct cardinfo *card = &cards[num_cards];
|
|
|
|
@ -929,7 +867,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x6155:
|
|
|
|
|
card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT;
|
|
|
|
|
card->flags |= UM_FLAG_NO_BYTE_STATUS |
|
|
|
|
|
UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT;
|
|
|
|
|
magic_number = 0x99;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -1013,9 +952,9 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|
|
|
|
dev_printk(KERN_INFO, &card->dev->dev,
|
|
|
|
|
"Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n",
|
|
|
|
|
card->mm_size,
|
|
|
|
|
(batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"),
|
|
|
|
|
batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled",
|
|
|
|
|
card->battery[0].good ? "OK" : "FAILURE",
|
|
|
|
|
(batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"),
|
|
|
|
|
batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled",
|
|
|
|
|
card->battery[1].good ? "OK" : "FAILURE");
|
|
|
|
|
|
|
|
|
|
set_fault_to_battery_status(card);
|
|
|
|
@ -1030,11 +969,11 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|
|
|
|
data = ~data;
|
|
|
|
|
data += 1;
|
|
|
|
|
|
|
|
|
|
if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME, card)) {
|
|
|
|
|
if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME,
|
|
|
|
|
card)) {
|
|
|
|
|
dev_printk(KERN_ERR, &card->dev->dev,
|
|
|
|
|
"Unable to allocate IRQ\n");
|
|
|
|
|
ret = -ENODEV;
|
|
|
|
|
|
|
|
|
|
goto failed_req_irq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1091,11 +1030,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_pci_remove
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void mm_pci_remove(struct pci_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
struct cardinfo *card = pci_get_drvdata(dev);
|
|
|
|
@ -1141,12 +1076,6 @@ static struct pci_driver mm_pci_driver = {
|
|
|
|
|
.remove = mm_pci_remove,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_init
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int __init mm_init(void)
|
|
|
|
|
{
|
|
|
|
|
int retval, i;
|
|
|
|
@ -1193,11 +1122,7 @@ out:
|
|
|
|
|
put_disk(mm_gendisk[i]);
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
-- mm_cleanup
|
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void __exit mm_cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|