Commit 98fb18b1 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] NCR5380 port to 2.5 first pass

There is still more work to do, the driver sucks in 2.4 and 2.5 but 2.5 has a
lot more of what is needed to make it work nicely. Basically NCR5380_main
probably has to become a thread in the next generation of the code.

This however seems to get it up and crawling
parent 99916cf4
......@@ -396,24 +396,21 @@ mrs[] = {
*
* Print the SCSI bus signals for debugging purposes
*
* Locks: none
* Locks: caller holds hostdata lock (not essential)
*/
static void NCR5380_print(struct Scsi_Host *instance)
{
NCR5380_local_declare();
unsigned long flags;
unsigned char status, data, basr, mr, icr, i;
NCR5380_setup(instance);
/* FIXME - this needs proper locking */
save_flags(flags);
cli();
data = NCR5380_read(CURRENT_SCSI_DATA_REG);
status = NCR5380_read(STATUS_REG);
mr = NCR5380_read(MODE_REG);
icr = NCR5380_read(INITIATOR_COMMAND_REG);
basr = NCR5380_read(BUS_AND_STATUS_REG);
restore_flags(flags);
printk("STATUS_REG: %02x ", status);
for (i = 0; signals[i].mask; ++i)
if (status & signals[i].mask)
......@@ -500,7 +497,8 @@ static unsigned long main_running = 0;
* request. main_running is checked/set here (in an inline function)
* rather than in NCR5380_main itself to reduce the chances of stack
* overflow.
*
* FIXME: NCR5380_main should probably be run with schedule_task or be a
* thread.
*/
static __inline__ void run_main(void)
......@@ -533,6 +531,7 @@ static __inline__ void run_main(void)
#endif
static struct Scsi_Host *expires_first = NULL;
static spinlock_t timer_lock; /* Guards expires list */
/*
* Function : int should_disconnect (unsigned char cmd)
......@@ -578,17 +577,21 @@ static int should_disconnect(unsigned char cmd)
/*
* Assumes instance->time_expires has been set in higher level code.
* We should move to a timer per host
*
* Locks: Caller must hold io_request_lock
* Locks: Takes the timer queue lock
*/
static int NCR5380_set_timer(struct Scsi_Host *instance)
{
struct Scsi_Host *tmp, **prev;
unsigned long flags;
if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
return -1;
}
spin_lock_irqsave(&timer_lock, flags);
for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
break;
......@@ -597,6 +600,8 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
*prev = instance;
mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
spin_unlock_irqrestore(&timer_lock, flags);
return 0;
}
......@@ -610,15 +615,15 @@ static int NCR5380_set_timer(struct Scsi_Host *instance)
*
* Doing something about unwanted reentrancy here might be useful
*
* Locks: disables irqs, takes and frees io_request_lock
* Locks: disables irqs, takes and frees the timer lock
*/
static void NCR5380_timer_fn(unsigned long unused)
{
struct Scsi_Host *instance;
unsigned long flags;
spin_lock_irq(&io_request_lock);
spin_lock_irqsave(&timer_lock, flags);
for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) {
instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer;
((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL;
......@@ -631,8 +636,10 @@ static void NCR5380_timer_fn(unsigned long unused)
usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
add_timer(&usleep_timer);
}
spin_unlock_irqrestore(&timer_lock, flags);
run_main();
spin_unlock_irq(&io_request_lock);
}
/**
......@@ -648,6 +655,7 @@ static inline void NCR5380_all_init(void)
dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
done = 1;
init_timer(&usleep_timer);
spin_lock_init(&timer_lock);
usleep_timer.function = NCR5380_timer_fn;
}
}
......@@ -777,7 +785,7 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
* Print commands in the various queues, called from NCR5380_abort
* and NCR5380_debug to aid debugging.
*
* Locks: called functions disable irqs, missing queue lock in proc call
* Locks: called functions disable irqs
*/
static void NCR5380_print_status(struct Scsi_Host *instance)
......@@ -872,7 +880,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
#ifdef PAS16_PUBLIC_RELEASE
SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
#endif
spin_lock_irq(&io_request_lock);
spin_lock_irq(instance->host_lock);
SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
......@@ -886,7 +894,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
spin_unlock_irq(&io_request_lock);
spin_unlock_irq(instance->host_lock);
*start = buffer;
if (pos - buffer < offset)
......@@ -1131,6 +1139,8 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
/* Run the coroutine if it isn't already running. */
/* FIMXE: drop any locks here */
run_main();
return 0;
}
......@@ -1276,20 +1286,22 @@ static void NCR5380_main(void) {
}
#ifndef DONT_USE_INTR
#include <linux/blk.h>
#include <linux/spinlock.h>
/**
* NCR5380_intr - generic NCR5380 irq handler
* @irq: interrupt number
* @dev_id: device info
* @regs: registers (unused)
*
* Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
* from the disconnected queue, and restarting NCR5380_main()
* as required.
*
* Locks: caller must hold the io_request lock.
* Locks: takes the needed instance locks
*/
static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
{
NCR5380_local_declare();
struct Scsi_Host *instance;
int done;
......@@ -1299,9 +1311,12 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
do {
done = 1;
/* The instance list is constant while the driver is
loaded */
for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
{
if (instance->irq == irq) {
spin_lock_irq(instance->host_lock);
/* Look for pending interrupts */
NCR5380_setup(instance);
basr = NCR5380_read(BUS_AND_STATUS_REG);
......@@ -1343,15 +1358,19 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
{
unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(&io_request_lock);
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout));
spin_lock_irq(&io_request_lock);
spin_unlock_irq(instance->host_lock);
/* FIXME: prove timer is always running here! */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout))
cpu_relax();
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout))
printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
}
#else /* NCR_TIMEOUT */
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK)
cpu_relax();
#endif
NCR5380_write(MODE_REG, MR_BASE);
......@@ -1363,33 +1382,15 @@ static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
#endif
}
} /* if BASR_IRQ */
spin_unlock_irq(instance->host_lock);
if (!done)
run_main();
} /* if (instance->irq == irq) */
}
} while (!done);
}
/**
* do_NCR5380_intr
* @irq: interrupt number
* @dev_id: device info
* @regs: registers (unused)
*
* Takes the io_request_lock and invokes the generic NCR5380 interrupt
* handler code
*
* Locks: takes and releases the io_request lock
*/
static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
NCR5380_intr(irq, dev_id, regs);
spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif
#endif
/**
* collect_stats - collect stats on a scsi command
......@@ -1450,7 +1451,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
* If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
*
* Locks: caller holds io_request_lock
* Locks: caller holds hostdata lock
*/
static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
......@@ -1493,12 +1494,13 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
{
unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
spin_unlock_irq(&io_request_lock);
spin_unlock_irq(instance->host_lock);
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
&& time_before(jiffies, timeout));
&& time_before(jiffies, timeout))
cpu_relax();
spin_lock_irq(&io_request_lock);
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout)) {
printk("scsi: arbitration timeout at %d\n", __LINE__);
......@@ -1624,6 +1626,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
we poll only once ech clock tick */
value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);
/* FIXME HZ=100 assumption ? */
if (!value && (hostdata->select_time < 25)) {
/* RvC: we still must wait for a device response */
hostdata->select_time++; /* after 25 ticks the device has failed */
......@@ -1692,9 +1695,10 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
{
unsigned long timeout = jiffies + NCR_TIMEOUT;
spin_unlock_irq(&io_request_lock);
while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout));
spin_lock_irq(&io_request_lock);
spin_unlock_irq(instance->host_lock);
while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout))
cpu_relax();
spin_lock_irq(instance->host_lock);
if (time_after_eq(jiffies, timeout)) {
printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
......@@ -1703,7 +1707,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
}
}
#else /* NCR_TIMEOUT */
while (!(NCR5380_read(STATUS_REG) & SR_REQ));
while (!(NCR5380_read(STATUS_REG) & SR_REQ))
cpu_relax();
#endif /* def NCR_TIMEOUT */
dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
......@@ -1886,7 +1891,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
* Issue a reset sequence to the NCR5380 and try and get the bus
* back into sane shape.
*
* Locks: caller holds io_request lock
* Locks: caller holds queue lock
* FIXME: sort this out and get new_eh running
*/
static void do_reset(struct Scsi_Host *host) {
......@@ -1907,7 +1913,8 @@ static void do_reset(struct Scsi_Host *host) {
*
* Returns : 0 on success, -1 on failure.
*
* Locks: io_request lock held by caller
* Locks: queue lock held by caller
* FIXME: sort this out and get new_eh running
*/
static int do_abort(struct Scsi_Host *host) {
......@@ -1930,7 +1937,8 @@ static int do_abort(struct Scsi_Host *host) {
* the target sees, so we just handshake.
*/
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
cpu_relax();
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
......@@ -2019,7 +2027,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*/
#if defined(PSEUDO_DMA) && defined(UNSAFE)
spin_unlock_irq(&io_request_lock);
spin_unlock_irq(instance->host_lock);
#endif
/* KLL May need eop and parity in 53c400 */
if (hostdata->flags & FLAG_NCR53C400)
......@@ -2228,7 +2236,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase
*count = 0;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
#if defined(PSEUDO_DMA) && defined(UNSAFE)
spin_lock_irq(&io_request_lock);
spin_lock_irq(instance->host_lock);
#endif /* defined(REAL_DMA_POLL) */
return foo;
#endif /* def REAL_DMA */
......@@ -2707,9 +2715,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
/*
* Wait for target to go into MSGIN.
* FIXME: timeout needed
*/
while (!(NCR5380_read(STATUS_REG) & SR_REQ));
while (!(NCR5380_read(STATUS_REG) & SR_REQ))
cpu_relax();
len = 1;
data = msg;
......@@ -2843,12 +2853,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
Scsi_Cmnd *tmp, **prev;
printk("scsi%d : aborting command\n", instance->host_no);
printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd);
NCR5380_print_status(instance);
printk("scsi%d : aborting command\n", instance->host_no);
printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
print_Scsi_Cmnd(cmd);
NCR5380_print_status(instance);
......@@ -2893,6 +2903,8 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* Case 2 : If the command hasn't been issued yet, we simply remove it
* from the issue queue.
*/
/* FIXME: check - I think we need the hostdata lock here */
/* KLL */
dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
......@@ -2903,12 +2915,12 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->result = DID_ABORT << 16;
dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
tmp->done(tmp);
return SCSI_ABORT_SUCCESS;
return SUCCESS;
}
#if (NDEBUG & NDEBUG_ABORT)
/* KLL */
else if (prev == tmp)
printk("scsi%d : LOOP\n", instance->host_no);
printk(KERN_ERR "scsi%d : LOOP\n", instance->host_no);
#endif
/*
......@@ -2924,7 +2936,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
if (hostdata->connected) {
dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
return SCSI_ABORT_NOT_RUNNING;
return FAILED;
}
/*
* Case 4: If the command is currently disconnected from the bus, and
......@@ -2956,7 +2968,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
if (NCR5380_select(instance, cmd, (int) cmd->tag))
return SCSI_ABORT_BUSY;
return FAILED;
dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
do_abort(instance);
......@@ -2968,7 +2980,7 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
tmp->done(tmp);
return SCSI_ABORT_SUCCESS;
return SUCCESS;
}
}
/*
......@@ -2980,30 +2992,68 @@ int NCR5380_abort(Scsi_Cmnd * cmd) {
* so we won't panic, but we will notify the user in case something really
* broke.
*/
printk("scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no);
return SCSI_ABORT_NOT_RUNNING;
printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no);
return FAILED;
}
/*
* Function : int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags)
* Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd)
*
* Purpose : reset the SCSI bus.
*
* Returns : SCSI_RESET_WAKEUP
* Returns : SUCCESS
*
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_reset
#ifndef NCR5380_bus_reset
static
#endif
int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int dummy) {
int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
NCR5380_print_status(cmd->host);
do_reset(cmd->host);
return SCSI_RESET_WAKEUP;
return SUCCESS;
}
/*
* Function : int NCR5380_device_reset (Scsi_Cmnd *cmd)
*
* Purpose : reset a SCSI device
*
* Returns : FAILED
*
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED;
}
/*
* Function : int NCR5380_host_reset (Scsi_Cmnd *cmd)
*
* Purpose : reset a SCSI device
*
* Returns : FAILED
*
* Locks: io_request_lock held by caller
*/
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd) {
NCR5380_local_declare();
NCR5380_setup(cmd->host);
return FAILED;
}
......@@ -304,10 +304,18 @@ static void NCR5380_print(struct Scsi_Host *instance);
static
#endif
int NCR5380_abort(Scsi_Cmnd * cmd);
#ifndef NCR5380_reset
#ifndef NCR5380_bus_reset
static
#endif
int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int reset_flags);
int NCR5380_bus_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_host_reset
static
#endif
int NCR5380_host_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_device_reset
static
#endif
int NCR5380_device_reset(Scsi_Cmnd * cmd);
#ifndef NCR5380_queue_command
static
#endif
......
......@@ -779,15 +779,15 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng
Scsi_Device *dev;
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#endif
save_flags(flags);
cli();
/* For now this is constant so we may walk it */
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr = scsi_ptr->next)
if (scsi_ptr->host_no == hostno)
break;
NCR5380_setup(scsi_ptr);
hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
spin_lock_irqsave(scsi_ptr->host_lock, flags);
PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
......@@ -874,7 +874,7 @@ int generic_NCR5380_proc_info(char *buffer, char **start, off_t offset, int leng
len -= offset;
if (len > length)
len = length;
restore_flags(flags);
spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
return len;
}
......
......@@ -48,7 +48,9 @@ int generic_NCR5380_abort(Scsi_Cmnd *);
int generic_NCR5380_detect(Scsi_Host_Template *);
int generic_NCR5380_release_resources(struct Scsi_Host *);
int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int generic_NCR5380_reset(Scsi_Cmnd *, unsigned int);
int generic_NCR5380_bus_reset(Scsi_Cmnd *);
int generic_NCR5380_host_reset(Scsi_Cmnd *);
int generic_NCR5380_device_reset(Scsi_Cmnd *);
int notyet_generic_proc_info (char *buffer ,char **start, off_t offset,
int length, int hostno, int inout);
const char* generic_NCR5380_info(struct Scsi_Host *);
......@@ -77,8 +79,10 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
release: generic_NCR5380_release_resources, \
info: (void *)generic_NCR5380_info, \
queuecommand: generic_NCR5380_queue_command, \
abort: generic_NCR5380_abort, \
reset: generic_NCR5380_reset, \
eh_abort_handler:generic_NCR5380_abort, \
eh_bus_reset_handler:generic_NCR5380_bus_reset, \
eh_device_reset_handler:generic_NCR5380_device_reset, \
eh_host_reset_handler:generic_NCR5380_host_reset, \
bios_param: NCR5380_BIOSPARAM, \
can_queue: CAN_QUEUE, \
this_id: 7, \
......@@ -154,7 +158,9 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
#define do_NCR5380_intr do_generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort
#define NCR5380_reset generic_NCR5380_reset
#define NCR5380_bus_reset generic_NCR5380_bus_reset
#define NCR5380_device_reset generic_NCR5380_device_reset
#define NCR5380_host_reset generic_NCR5380_host_reset
#define NCR5380_pread generic_NCR5380_pread
#define NCR5380_pwrite generic_NCR5380_pwrite
#define NCR5380_proc_info notyet_generic_proc_info
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment