forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
267 lines
6.3 KiB
267 lines
6.3 KiB
/* |
|
backpack.c (c) 2001 Micro Solutions Inc. |
|
Released under the terms of the GNU General Public license |
|
|
|
backpack.c is a low-level protocol driver for the Micro Solutions |
|
"BACKPACK" parallel port IDE adapter |
|
(Works on Series 6 drives) |
|
|
|
Written by: Ken Hahn ([email protected]) |
|
Clive Turvey ([email protected]) |
|
|
|
*/ |
|
|
|
/* |
|
This is Ken's linux wrapper for the PPC library |
|
Version 1.0.0 is the backpack driver for which source is not available |
|
Version 2.0.0 is the first to have source released |
|
Version 2.0.1 is the "Cox-ified" source code |
|
Version 2.0.2 - fixed version string usage, and made ppc functions static |
|
*/ |
|
|
|
|
|
#define BACKPACK_VERSION "2.0.2" |
|
|
|
#include <linux/module.h> |
|
#include <linux/init.h> |
|
#include <linux/kernel.h> |
|
#include <linux/slab.h> |
|
#include <linux/types.h> |
|
#include <asm/io.h> |
|
#include <linux/parport.h> |
|
|
|
#include "ppc6lnx.c" |
|
#include "paride.h" |
|
|
|
/* PARAMETERS */ |
|
static bool verbose; /* set this to 1 to see debugging messages and whatnot */ |
|
|
|
|
|
#define PPCSTRUCT(pi) ((Interface *)(pi->private)) |
|
|
|
/****************************************************************/ |
|
/* |
|
ATAPI CDROM DRIVE REGISTERS |
|
*/ |
|
#define ATAPI_DATA 0 /* data port */ |
|
#define ATAPI_ERROR 1 /* error register (read) */ |
|
#define ATAPI_FEATURES 1 /* feature register (write) */ |
|
#define ATAPI_INT_REASON 2 /* interrupt reason register */ |
|
#define ATAPI_COUNT_LOW 4 /* byte count register (low) */ |
|
#define ATAPI_COUNT_HIGH 5 /* byte count register (high) */ |
|
#define ATAPI_DRIVE_SEL 6 /* drive select register */ |
|
#define ATAPI_STATUS 7 /* status port (read) */ |
|
#define ATAPI_COMMAND 7 /* command port (write) */ |
|
#define ATAPI_ALT_STATUS 0x0e /* alternate status reg (read) */ |
|
#define ATAPI_DEVICE_CONTROL 0x0e /* device control (write) */ |
|
/****************************************************************/ |
|
|
|
static int bpck6_read_regr(PIA *pi, int cont, int reg) |
|
{ |
|
unsigned int out; |
|
|
|
/* check for bad settings */ |
|
if (reg<0 || reg>7 || cont<0 || cont>2) |
|
{ |
|
return(-1); |
|
} |
|
out=ppc6_rd_port(PPCSTRUCT(pi),cont?reg|8:reg); |
|
return(out); |
|
} |
|
|
|
static void bpck6_write_regr(PIA *pi, int cont, int reg, int val) |
|
{ |
|
/* check for bad settings */ |
|
if (reg>=0 && reg<=7 && cont>=0 && cont<=1) |
|
{ |
|
ppc6_wr_port(PPCSTRUCT(pi),cont?reg|8:reg,(u8)val); |
|
} |
|
} |
|
|
|
static void bpck6_write_block( PIA *pi, char * buf, int len ) |
|
{ |
|
ppc6_wr_port16_blk(PPCSTRUCT(pi),ATAPI_DATA,buf,(u32)len>>1); |
|
} |
|
|
|
static void bpck6_read_block( PIA *pi, char * buf, int len ) |
|
{ |
|
ppc6_rd_port16_blk(PPCSTRUCT(pi),ATAPI_DATA,buf,(u32)len>>1); |
|
} |
|
|
|
static void bpck6_connect ( PIA *pi ) |
|
{ |
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "connect\n"); |
|
} |
|
|
|
if(pi->mode >=2) |
|
{ |
|
PPCSTRUCT(pi)->mode=4+pi->mode-2; |
|
} |
|
else if(pi->mode==1) |
|
{ |
|
PPCSTRUCT(pi)->mode=3; |
|
} |
|
else |
|
{ |
|
PPCSTRUCT(pi)->mode=1; |
|
} |
|
|
|
ppc6_open(PPCSTRUCT(pi)); |
|
ppc6_wr_extout(PPCSTRUCT(pi),0x3); |
|
} |
|
|
|
static void bpck6_disconnect ( PIA *pi ) |
|
{ |
|
if(verbose) |
|
{ |
|
printk("disconnect\n"); |
|
} |
|
ppc6_wr_extout(PPCSTRUCT(pi),0x0); |
|
ppc6_close(PPCSTRUCT(pi)); |
|
} |
|
|
|
static int bpck6_test_port ( PIA *pi ) /* check for 8-bit port */ |
|
{ |
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "PARPORT indicates modes=%x for lp=0x%lx\n", |
|
((struct pardevice*)(pi->pardev))->port->modes, |
|
((struct pardevice *)(pi->pardev))->port->base); |
|
} |
|
|
|
/*copy over duplicate stuff.. initialize state info*/ |
|
PPCSTRUCT(pi)->ppc_id=pi->unit; |
|
PPCSTRUCT(pi)->lpt_addr=pi->port; |
|
|
|
/* look at the parport device to see if what modes we can use */ |
|
if(((struct pardevice *)(pi->pardev))->port->modes & |
|
(PARPORT_MODE_EPP) |
|
) |
|
{ |
|
return 5; /* Can do EPP*/ |
|
} |
|
else if(((struct pardevice *)(pi->pardev))->port->modes & |
|
(PARPORT_MODE_TRISTATE) |
|
) |
|
{ |
|
return 2; |
|
} |
|
else /*Just flat SPP*/ |
|
{ |
|
return 1; |
|
} |
|
} |
|
|
|
static int bpck6_probe_unit ( PIA *pi ) |
|
{ |
|
int out; |
|
|
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "PROBE UNIT %x on port:%x\n",pi->unit,pi->port); |
|
} |
|
|
|
/*SET PPC UNIT NUMBER*/ |
|
PPCSTRUCT(pi)->ppc_id=pi->unit; |
|
|
|
/*LOWER DOWN TO UNIDIRECTIONAL*/ |
|
PPCSTRUCT(pi)->mode=1; |
|
|
|
out=ppc6_open(PPCSTRUCT(pi)); |
|
|
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "ppc_open returned %2x\n",out); |
|
} |
|
|
|
if(out) |
|
{ |
|
ppc6_close(PPCSTRUCT(pi)); |
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "leaving probe\n"); |
|
} |
|
return(1); |
|
} |
|
else |
|
{ |
|
if(verbose) |
|
{ |
|
printk(KERN_DEBUG "Failed open\n"); |
|
} |
|
return(0); |
|
} |
|
} |
|
|
|
static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose ) |
|
{ |
|
char *mode_string[5]= |
|
{"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; |
|
|
|
printk("%s: BACKPACK Protocol Driver V"BACKPACK_VERSION"\n",pi->device); |
|
printk("%s: Copyright 2001 by Micro Solutions, Inc., DeKalb IL.\n",pi->device); |
|
printk("%s: BACKPACK %s, Micro Solutions BACKPACK Drive at 0x%x\n", |
|
pi->device,BACKPACK_VERSION,pi->port); |
|
printk("%s: Unit: %d Mode:%d (%s) Delay %d\n",pi->device, |
|
pi->unit,pi->mode,mode_string[pi->mode],pi->delay); |
|
} |
|
|
|
static int bpck6_init_proto(PIA *pi) |
|
{ |
|
Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL); |
|
|
|
if (p) { |
|
pi->private = (unsigned long)p; |
|
return 0; |
|
} |
|
|
|
printk(KERN_ERR "%s: ERROR COULDN'T ALLOCATE MEMORY\n", pi->device); |
|
return -1; |
|
} |
|
|
|
static void bpck6_release_proto(PIA *pi) |
|
{ |
|
kfree((void *)(pi->private)); |
|
} |
|
|
|
static struct pi_protocol bpck6 = { |
|
.owner = THIS_MODULE, |
|
.name = "bpck6", |
|
.max_mode = 5, |
|
.epp_first = 2, /* 2-5 use epp (need 8 ports) */ |
|
.max_units = 255, |
|
.write_regr = bpck6_write_regr, |
|
.read_regr = bpck6_read_regr, |
|
.write_block = bpck6_write_block, |
|
.read_block = bpck6_read_block, |
|
.connect = bpck6_connect, |
|
.disconnect = bpck6_disconnect, |
|
.test_port = bpck6_test_port, |
|
.probe_unit = bpck6_probe_unit, |
|
.log_adapter = bpck6_log_adapter, |
|
.init_proto = bpck6_init_proto, |
|
.release_proto = bpck6_release_proto, |
|
}; |
|
|
|
static int __init bpck6_init(void) |
|
{ |
|
printk(KERN_INFO "bpck6: BACKPACK Protocol Driver V"BACKPACK_VERSION"\n"); |
|
printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n"); |
|
if(verbose) |
|
printk(KERN_DEBUG "bpck6: verbose debug enabled.\n"); |
|
return paride_register(&bpck6); |
|
} |
|
|
|
static void __exit bpck6_exit(void) |
|
{ |
|
paride_unregister(&bpck6); |
|
} |
|
|
|
MODULE_LICENSE("GPL"); |
|
MODULE_AUTHOR("Micro Solutions Inc."); |
|
MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE"); |
|
module_param(verbose, bool, 0644); |
|
module_init(bpck6_init) |
|
module_exit(bpck6_exit)
|
|
|