| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | 
							- /*
 -    Kernel module for the dp83820 flash write utility. This code was written
 -    by Dave Ashley for NXTV, Inc.
 -    Copyright 2004 by NXTV, Inc.
 -    Written 20040219 by Dave Ashley.
 - 
 -    This code is released under the terms of the GPL. No warranty.
 - 
 -    THEORY: The dp83820 bootrom interface is flawed in that you can't
 -    read or write a single byte at a time, and this is required in order
 -    to write to flash devices like the AT29C512. So the workaround is
 -    to use the chips ability to map into memory the bootrom, then the cpu
 -    can directly do byte accesses.
 - 
 -    The problem is that a "feature" of the dp83820 is that when you map
 -    in the bootrom, you conveniently lose access to the PCI registers.
 -    So we need to do this in kernel space and wrap every access to the
 -    bootrom within interrupt_disable/restore, in case a network interrupt
 -    were to come in.
 - 
 -    This kernel module is very simple, it just creates a proc file
 -    /proc/dp83820
 -    If you write 3 bytes to this file you are doing a write to the flashrom:
 - 
 - Byte 1   2    3
 -    ALOW AHIGH DATA
 - 
 -    If you write 2 bytes to this file you are doing a read from the flashrom:
 - Byte 1   2
 -    ALOW AHIGH
 -    Then the next read from the file will return a single byte of what
 -    was at that location.
 - 
 -    You only get one shot at accessing the proc file, you need to then
 -    close/open if you want to do another access. This could probably be
 -    cleaned up pretty easily so more accesses can be done without having
 -    to close/open the file.     
 - 
 - */
 - 
 - 
 - #include <linux/config.h>
 - #include <linux/kernel.h>
 - #include <linux/sched.h>
 - #include <linux/errno.h>
 - #include <linux/ioport.h>
 - #include <linux/interrupt.h>
 - #include <linux/pci.h>
 - #include <linux/spinlock.h>
 - #include <linux/proc_fs.h>
 - #include <linux/module.h>
 - 
 - 
 - #define PROCNAME "dp83820"
 - 
 - struct pci_dev *mydev=0;
 - unsigned long loc;
 - unsigned char *addr=0;
 - 
 - unsigned char lastread;
 - 
 - 
 - int my_read_proc(char *buf, char **start,off_t offset,int count, int *eof,void *data)
 - {
 - int retval=0;
 - 
 - 	if(count>0)
 - 	{
 - 		buf[0]=lastread;
 - 		retval=1;
 - 	}
 - 
 - 	*eof=1;
 - 
 - 	return retval;
 - }
 - 
 - int my_write_proc(struct file *file, const char *buffer, unsigned long count,
 - 		void *data)
 - {
 - unsigned char *msg;
 - 
 - unsigned long flags;
 - 
 - 	msg=(void *)buffer;
 - 	save_flags(flags);
 - 	cli();
 - 	pci_write_config_dword(mydev, 0x30, loc | 1);
 - 
 - 	switch(count)
 - 	{
 - 		case 2:
 - 			lastread=addr[msg[0] | (msg[1]<<8)];
 - 			break;
 - 		case 3:
 - 			addr[msg[0] | (msg[1]<<8)] = msg[2];
 - 			break;
 - 	}
 - 	pci_write_config_dword(mydev, 0x30, loc);
 - 	restore_flags(flags);
 - 	return count;
 - }
 - 
 - 
 - struct proc_dir_entry *de=0;
 - 
 - int __init init_module(void)
 - {
 - int found=0;
 - 	mydev=0;
 - 	pci_for_each_dev(mydev)
 - 	{
 - 		if(mydev->vendor==0x100b && mydev->device==0x0022)
 - 		{
 - 			found=1;
 - 			break;
 - 		}
 - 	}
 - 	if(!found)
 - 	{
 - 		printk("Could not find DP83820 network device\n");
 - 		return ENODEV;
 - 	}
 - 
 - 	de=create_proc_entry(PROCNAME,0,0);
 - 	if(!de)
 - 		return -1;
 - 	de->data=0;
 - 	de->read_proc=my_read_proc;
 - 	de->write_proc=my_write_proc;
 - 
 - 	loc=mydev->resource[PCI_ROM_RESOURCE].start;
 - 	addr=ioremap_nocache(loc,0x10000);
 - 
 - 
 - 	return 0;
 - }
 - 
 - void cleanup_module(void)
 - {
 - 	if(de)
 - 	{
 - 		remove_proc_entry(PROCNAME,0);
 - 		de=0;
 - 	}
 - 	if(addr)
 - 	{
 - 		iounmap(addr);
 - 		addr=0;
 - 	}
 - }
 
 
  |