Commit a96e1f22 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Import 2.0.1

parent 81e05330
......@@ -59,7 +59,8 @@ void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
* - kfree when msg has been sent
*/
if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb)) < 0)
if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb,
chan->proto)) < 0)
{
printk("capi_conn_req failed\n");
return;
......
......@@ -58,7 +58,7 @@
*
*/
int capi_conn_req(const char * calledPN, struct sk_buff **skb)
int capi_conn_req(const char * calledPN, struct sk_buff **skb, int proto)
{
ushort len;
......@@ -80,6 +80,9 @@ int capi_conn_req(const char * calledPN, struct sk_buff **skb)
len = 18 + strlen(calledPN);
if (proto == ISDN_PROTO_L2_TRANS)
len++;
if ((*skb = dev_alloc_skb(len)) == NULL) {
printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n");
......@@ -89,11 +92,21 @@ int capi_conn_req(const char * calledPN, struct sk_buff **skb)
/* InfoElmMask */
*((ushort*) skb_put(*skb, 2)) = AppInfoMask;
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 2; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x88; /* BC0.Octect3 - Digital Information */
*(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 - */
if (proto == ISDN_PROTO_L2_TRANS)
{
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 3; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x80; /* Speech */
*(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */
*(skb_put(*skb, 1)) = 0x23; /* A-law */
}
else
{
/* Bearer Capability - Mandatory*/
*(skb_put(*skb, 1)) = 2; /* BC0.Length */
*(skb_put(*skb, 1)) = 0x88; /* Digital Information */
*(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 */
}
/* Bearer Capability - Optional*/
*(skb_put(*skb, 1)) = 0; /* BC1.Length = 0 */
......@@ -220,16 +233,19 @@ int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb,
*(skb_put(*skb, 1)) = 0x05; /* LAPB */
break;
case ISDN_PROTO_L2_HDLC:
#ifdef DEBUG
printk(KERN_DEBUG "HDLC\n"); /* HDLC */
#endif
*(skb_put(*skb, 1)) = 0x02;
break;
case ISDN_PROTO_L2_TRANS:
/*
* Voice (a-law)
*/
*(skb_put(*skb, 1)) = 0x06;
break;
default:
#ifdef DEBUG
printk(KERN_DEBUG "Transparent\n");
#endif
*(skb_put(*skb, 1)) = 0x03;
*(skb_put(*skb, 1)) = 0x03;
break;
}
......
......@@ -22,7 +22,8 @@
#define AppInfoMask REQ_CAUSE|REQ_DISPLAY|REQ_USER_TO_USER
/* Connection Setup */
extern int capi_conn_req(const char * calledPN, struct sk_buff **buf);
extern int capi_conn_req(const char * calledPN, struct sk_buff **buf,
int proto);
extern int capi_decode_conn_conf(struct pcbit_chan * chan, struct sk_buff *skb,
int *complete);
......
......@@ -11,6 +11,14 @@
* PCBIT-D interface with isdn4linux
*/
/*
* Fixes:
*
* Nuno Grilo <l38486@alfa.ist.utl.pt>
* fixed msn_list NULL pointer dereference.
*
*/
#define __NO_VERSION__
#include <linux/module.h>
......@@ -109,7 +117,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev->b2->id = 1;
dev->qdelivery.next = 0;
dev->qdelivery.next = NULL;
dev->qdelivery.sync = 0;
dev->qdelivery.routine = pcbit_deliver;
dev->qdelivery.data = dev;
......@@ -152,8 +160,8 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev_if->channels = 2;
dev_if->features = ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_L2_HDLC;
dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS );
dev_if->writebuf_skb = pcbit_xmit;
dev_if->writebuf = NULL;
......@@ -1051,7 +1059,8 @@ static void pcbit_clear_msn(struct pcbit_dev *dev)
static void pcbit_set_msn(struct pcbit_dev *dev, char *list)
{
struct msn_entry *ptr, *back;
struct msn_entry *ptr;
struct msn_entry *back = NULL;
char *cp, *sp;
int len;
......@@ -1070,7 +1079,8 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list)
return;
}
for (back=dev->msn_list; back->next; back=back->next);
if (dev->msn_list)
for (back=dev->msn_list; back->next; back=back->next);
sp = list;
......@@ -1128,10 +1138,3 @@ static int pcbit_check_msn(struct pcbit_dev *dev, char *msn)
return 0;
}
......@@ -288,15 +288,10 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan,
save_flags(flags);
cli();
if (chan->fsm_timer.function) {
del_timer(&chan->fsm_timer);
chan->fsm_timer.function = NULL;
}
for (action = fsm_table; action->init != 0xff; action++)
if (action->init == chan->fsm_state && action->event == event)
break;
if (action->init == 0xff) {
......@@ -305,6 +300,11 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan,
return;
}
if (chan->fsm_timer.function) {
del_timer(&chan->fsm_timer);
chan->fsm_timer.function = NULL;
}
chan->fsm_state = action->final;
pcbit_state_change(dev, chan, action->init, event, action->final);
......
......@@ -58,16 +58,7 @@
/*
* task queue struct
*/
struct tq_struct *tq_delivery=NULL;
static void do_pcbit_bh(task_queue *list)
{
run_task_queue(list);
}
struct tq_struct run_delivery= {
0, 0, (void *)(void *) do_pcbit_bh, &tq_delivery,
};
/*
......@@ -87,7 +78,6 @@ void pcbit_deliver(void * data);
static void pcbit_transmit(struct pcbit_dev * dev);
static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack);
static void pcbit_frame_read(struct pcbit_dev * dev, unsigned char read_seq);
static void pcbit_l2_error(struct pcbit_dev *dev);
static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info);
......@@ -95,11 +85,10 @@ static void pcbit_l2_err_recover(unsigned long data);
static void pcbit_firmware_bug(struct pcbit_dev * dev);
static void pcbit_sched_delivery(struct pcbit_dev *dev)
static __inline__ void pcbit_sched_delivery(struct pcbit_dev *dev)
{
queue_task_irq_off(&dev->qdelivery, &tq_delivery);
queue_task_irq_off(&run_delivery, &tq_immediate);
mark_bh(IMMEDIATE_BH);
queue_task(&dev->qdelivery, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
......@@ -195,11 +184,10 @@ static void pcbit_transmit(struct pcbit_dev * dev)
unacked = (dev->send_seq + (8 - dev->unack_seq) ) & 0x07;
if (dev->free > 16 && dev->write_queue && unacked < 7) {
save_flags(flags);
cli();
save_flags(flags);
cli();
if (dev->free > 16 && dev->write_queue && unacked < 7) {
if (!dev->w_busy)
dev->w_busy = 1;
......@@ -209,11 +197,12 @@ static void pcbit_transmit(struct pcbit_dev * dev)
return;
}
restore_flags(flags);
frame = dev->write_queue;
free = dev->free;
restore_flags(flags);
if (frame->copied == 0) {
/* Type 0 frame */
......@@ -311,12 +300,15 @@ static void pcbit_transmit(struct pcbit_dev * dev)
dev->w_busy = 0;
restore_flags(flags);
}
#ifdef DEBUG
else
{
restore_flags(flags);
#ifdef DEBUG
printk(KERN_DEBUG "unacked %d free %d write_queue %s\n",
unacked, dev->free, dev->write_queue ? "not empty" :
"empty");
"empty");
#endif
}
}
......@@ -334,29 +326,31 @@ void pcbit_deliver(void * data)
save_flags(flags);
cli();
/* get frame from queue */
if (!(frame=dev->read_queue)) {
while((frame=dev->read_queue))
{
dev->read_queue = frame->next;
restore_flags(flags);
return;
}
dev->read_queue = frame->next;
restore_flags(flags);
msg.cpu = 0;
msg.proc = 0;
msg.cmd = frame->skb->data[2];
msg.scmd = frame->skb->data[3];
msg.cpu = 0;
msg.proc = 0;
msg.cmd = frame->skb->data[2];
msg.scmd = frame->skb->data[3];
frame->refnum = *((ushort*) frame->skb->data + 4);
frame->msg = *((ulong*) &msg);
skb_pull(frame->skb, 6);
frame->refnum = *((ushort*) frame->skb->data + 4);
frame->msg = *((ulong*) &msg);
skb_pull(frame->skb, 6);
pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len,
frame->refnum);
pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len,
frame->refnum);
kfree(frame);
kfree(frame);
save_flags(flags);
cli();
}
restore_flags(flags);
}
/*
......@@ -517,8 +511,7 @@ static void pcbit_receive(struct pcbit_dev * dev)
}
else
dev->read_queue = frame;
pcbit_sched_delivery(dev);
restore_flags(flags);
}
......@@ -572,7 +565,6 @@ void pcbit_irq_handler(int interrupt, void * devptr, struct pt_regs *regs)
{
struct pcbit_dev * dev;
u_char info, ack_seq, read_seq;
u_char ack_int = 1;
dev = (struct pcbit_dev *) devptr;
......@@ -618,33 +610,27 @@ void pcbit_irq_handler(int interrupt, void * devptr, struct pt_regs *regs)
read_seq = (info & 0x07U);
dev->interrupt = 0;
sti();
/*
* Bottom Half
* Runs with ints enabled
*/
if (read_seq != dev->rcv_seq)
{
pcbit_frame_read(dev, read_seq);
ack_int = 0;
while (read_seq != dev->rcv_seq)
{
pcbit_receive(dev);
dev->rcv_seq = (dev->rcv_seq + 1) % 8;
}
pcbit_sched_delivery(dev);
}
if (ack_seq != dev->unack_seq)
{
pcbit_recv_ack(dev, ack_seq);
ack_int = 0;
}
if (ack_int)
{
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
info = dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}
writeb(info, dev->sh_mem + BANK4);
}
......@@ -685,17 +671,19 @@ static void pcbit_l2_err_recover(unsigned long data)
del_timer(&dev->error_recover_timer);
if (dev->w_busy || dev->r_busy)
{
init_timer(&dev->error_recover_timer);
dev->error_recover_timer.expires = jiffies + ERRTIME;
add_timer(&dev->error_recover_timer);
return;
}
{
init_timer(&dev->error_recover_timer);
dev->error_recover_timer.expires = jiffies + ERRTIME;
add_timer(&dev->error_recover_timer);
return;
}
dev->w_busy = dev->r_busy = 1;
if (dev->read_frame) {
if (dev->read_frame->skb) {
if (dev->read_frame)
{
if (dev->read_frame->skb)
{
dev->read_frame->skb->free = 1;
kfree_skb(dev->read_frame->skb, FREE_READ);
}
......@@ -704,7 +692,8 @@ static void pcbit_l2_err_recover(unsigned long data)
}
if (dev->write_queue) {
if (dev->write_queue)
{
frame = dev->write_queue;
#ifdef FREE_ON_ERROR
dev->write_queue = dev->write_queue->next;
......@@ -775,14 +764,20 @@ static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack)
{
if (dev->send_seq > dev->unack_seq)
if (ack <= dev->unack_seq || ack > dev->send_seq)
if (ack <= dev->unack_seq || ack > dev->send_seq)
{
printk("layer 2 ack unacceptable - dev %d", dev->id);
printk(KERN_DEBUG
"layer 2 ack unacceptable - dev %d",
dev->id);
pcbit_l2_error(dev);
}
else
if (ack > dev->send_seq && ack <= dev->unack_seq) {
printk("layer 2 ack unacceptable - dev %d", dev->id);
if (ack > dev->send_seq && ack <= dev->unack_seq)
{
printk(KERN_DEBUG
"layer 2 ack unacceptable - dev %d",
dev->id);
pcbit_l2_error(dev);
}
......@@ -805,55 +800,9 @@ static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack)
if (dev->send_seq == lsend_seq)
break;
count++;
}
if (!count) {
u_char info;
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}
count++;
}
}
else
printk(KERN_DEBUG "recv_ack: unacked = 0\n");
}
static void pcbit_frame_read(struct pcbit_dev * dev, unsigned char read_seq)
{
unsigned long flags;
int busy;
u_char info;
save_flags(flags);
cli();
if (!(busy=dev->r_busy))
dev->r_busy = 1;
restore_flags(flags);
if (busy)
return;
while (read_seq != dev->rcv_seq) {
pcbit_receive(dev);
dev->rcv_seq = (dev->rcv_seq + 1) % 8;
}
dev->r_busy = 0;
info = 0;
info |= dev->rcv_seq << 3;
info |= dev->send_seq;
writeb(info, dev->sh_mem + BANK4);
}
/* $Id: callc.c,v 1.11 1996/06/07 12:32:20 fritz Exp $
/* $Id: callc.c,v 1.13 1996/06/24 17:15:55 fritz Exp $
*
* $Log: callc.c,v $
* Revision 1.13 1996/06/24 17:15:55 fritz
* corrected return code of teles_writebuf()
*
* Revision 1.12 1996/06/12 16:15:33 fritz
* Extended user-configurable debugging flags.
*
* Revision 1.11 1996/06/07 12:32:20 fritz
* More changes to support suspend/resume.
*
......@@ -1297,8 +1303,10 @@ distr_debug(void)
chanlist[i].ds.l2.l2m.debug = debugflags & 16;
}
for (i = 0; i < nrcards; i++)
if (cards[i].sp)
if (cards[i].sp) {
cards[i].sp->dlogflag = debugflags & 4;
cards[i].sp->debug = debugflags & 32;
}
}
int
......@@ -1419,12 +1427,15 @@ teles_writebuf(int id, int chan, const u_char * buf, int count, int user)
if (!chanp->data_open) {
printk(KERN_DEBUG "teles_writebuf: channel not open\n");
return -ENOMEM;
return -EIO;
}
err = BufPoolGet(&ibh, st->l1.sbufpool, GFP_ATOMIC, st, 21);
if (err)
return -ENOMEM;
/* Must return 0 here, since this is not an error
* but a temporary lack of resources.
*/
return 0;
ptr = DATAPTR(ibh);
if (chanp->lc_b.l2_establish)
......
/* $Id: card.c,v 1.9 1996/06/06 14:42:09 fritz Exp $
/* $Id: card.c,v 1.12 1996/06/24 17:16:52 fritz Exp $
*
* card.c low level stuff for the Teles S0 isdn card
*
......@@ -7,6 +7,16 @@
* Beat Doebeli log all D channel traffic
*
* $Log: card.c,v $
* Revision 1.12 1996/06/24 17:16:52 fritz
* Added check for misconfigured membase.
*
* Revision 1.11 1996/06/14 03:30:37 fritz
* Added recovery from EXIR 40 interrupt.
* Some cleanup.
*
* Revision 1.10 1996/06/11 14:57:20 hipp
* minor changes to ensure, that SKBs are sent in the right order
*
* Revision 1.9 1996/06/06 14:42:09 fritz
* Bugfix: forgot hsp-> in last change.
*
......@@ -52,7 +62,6 @@
#include <linux/interrupt.h>
#undef DCHAN_VERBOSE
#define FRITZ_EXPERIMENTAL
extern void tei_handler(struct PStack *st, byte pr,
struct BufHeader *ibh);
......@@ -215,16 +224,9 @@ waitforCEC_3(int iobase, byte hscx)
static inline void
waitforXFW_0(byte * base, byte hscx)
{
#ifdef FRITZ_EXPERIMENTAL
long to = 20;
while ((!(readhscx_0(base, hscx, HSCX_STAR) & 0x44)==0x40) && to) {
#else
long to = 10;
waitforCEC_0(base, hscx);
while ((!(readhscx_0(base, hscx, HSCX_STAR) & 0x40)) && to) {
#endif
udelay(5);
to--;
}
......@@ -235,16 +237,9 @@ waitforXFW_0(byte * base, byte hscx)
static inline void
waitforXFW_3(int iobase, byte hscx)
{
#ifdef FRITZ_EXPERIMENTAL
long to = 20;
while ((!(readhscx_3(iobase, hscx, HSCX_STAR) & 0x44)==0x40) && to) {
#else
long to = 10;
waitforCEC_3(iobase, hscx);
while ((!(readhscx_3(iobase, hscx, HSCX_STAR) & 0x40)) && to) {
#endif
udelay(5);
to--;
}
......@@ -507,10 +502,10 @@ hscx_interrupt(struct IsdnCardState *sp, byte val, byte hscx)
} else {
if (hsp->releasebuf)
BufPoolRelease(hsp->xmtibh);
hsp->xmtibh = NULL;
hsp->sendptr = 0;
if (hsp->st->l4.l1writewakeup)
hsp->st->l4.l1writewakeup(hsp->st);
hsp->xmtibh = NULL;
}
if (!BufQueueUnlink(&hsp->xmtibh, &hsp->sq)) {
hsp->releasebuf = !0;
......@@ -709,7 +704,7 @@ isac_new_ph(struct IsdnCardState *sp)
static void
teles_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
byte val, val2, r, exval;
byte val, r, exval;
struct IsdnCardState *sp;
unsigned int count;
struct HscxState *hsp;
......@@ -725,11 +720,20 @@ teles_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (val & 0x01) {
hsp = sp->hs + 1;
exval = READHSCX(sp->membase, sp->iobase, 1, HSCX_EXIR);
if ((hsp->mode == 1) || (exval == 0x40))
hscx_fill_fifo(hsp);
else
printk(KERN_WARNING "HSCX B EXIR %x xmitbh %lx rcvibh %lx\n",
exval, (long) hsp->xmtibh, (long) hsp->rcvibh);
if (exval == 0x40) {
if (hsp->mode == 1)
hscx_fill_fifo(hsp);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
hsp->sendptr = 0;
WRITEHSCX_CMDR(hsp->membase, hsp->iobase,
hsp->hscx, 0x01);
printk(KERN_DEBUG "HSCX B EXIR %x\n", exval);
}
} else
printk(KERN_WARNING "HSCX B EXIR %x\n", exval);
}
if (val & 0xf8) {
if (sp->debug)
......@@ -739,33 +743,28 @@ teles_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (val & 0x02) {
hsp = sp->hs;
exval = READHSCX(sp->membase, sp->iobase, 0, HSCX_EXIR);
if ((hsp->mode == 1) && (exval == 0x40))
hscx_fill_fifo(hsp);
else
printk(KERN_WARNING "HSCX A EXIR %x\n",exval);
if (exval == 0x40) {
if (hsp->mode == 1)
hscx_fill_fifo(hsp);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
hsp->sendptr = 0;
WRITEHSCX_CMDR(hsp->membase, hsp->iobase,
hsp->hscx, 0x01);
printk(KERN_DEBUG "HSCX A EXIR %x\n", exval);
}
} else
printk(KERN_WARNING "HSCX A EXIR %x\n", exval);
}
/* ??? Why do that vvvvvvvvvvvvvvvvvvvvv different on Teles 16-3 ??? */
if (sp->membase) {
if (val & 0x04) {
val = readhscx_0(sp->membase, 0, HSCX_ISTA);
if (sp->debug)
printk(KERN_DEBUG "HSCX A interrupt %x\n",
val);
hscx_interrupt(sp, val, 0);
}
} else {
val2 = readhscx_3(sp->iobase, 0, HSCX_ISTA);
if (val & 0x04) {
val = READHSCX(sp->membase, sp->iobase, 0, HSCX_ISTA);
if (sp->debug)
printk(KERN_DEBUG "HSCX A ISTA %x\n", val2);
if (val & 0x04) {
if (sp->debug)
printk(KERN_DEBUG "HSCX A interrupt %x\n",
val2);
hscx_interrupt(sp, val2, 0);
}
printk(KERN_DEBUG "HSCX A interrupt %x\n",
val);
hscx_interrupt(sp, val, 0);
}
/* ??? Why do that ^^^^^^^^^^^^^^^^^^^^^ different on Teles 16-3 ??? */
val = READISAC(sp->membase, sp->iobase, ISAC_ISTA);
......@@ -1083,6 +1082,13 @@ checkcard(int cardnr)
byte cfval, val;
struct IsdnCard *card = cards + cardnr;
if (card->membase)
if ((unsigned long)card->membase < 0x10000) {
(unsigned long)card->membase <<= 4;
printk(KERN_INFO
"Teles membase configured DOSish, assuming 0x%lx\n",
(unsigned long)card->membase);
}
if (!card->iobase) {
if (card->membase) {
printk(KERN_NOTICE
......@@ -1090,7 +1096,7 @@ checkcard(int cardnr)
(long) card->membase, card->interrupt,
(card->protocol == ISDN_PTYPE_1TR6) ?
"1TR6" : "EDSS1");
printk(KERN_INFO "HSCX version A: %x B:%x\n",
printk(KERN_INFO "HSCX version A:%x B:%x\n",
readhscx_0(card->membase, 0, HSCX_VSTR) & 0xf,
readhscx_0(card->membase, 1, HSCX_VSTR) & 0xf);
}
......@@ -1736,12 +1742,18 @@ hscx_l2l1(struct PStack *st, int pr,
struct IsdnCardState *sp = (struct IsdnCardState *)
st->l1.hardware;
struct HscxState *hsp = sp->hs + st->l1.hscx;
long flags;
switch (pr) {
case (PH_DATA):
if (hsp->xmtibh)
save_flags(flags);
cli();
if (hsp->xmtibh) {
BufQueueLink(&hsp->sq, ibh);
restore_flags(flags);
}
else {
restore_flags(flags);
hsp->xmtibh = ibh;
hsp->sendptr = 0;
hsp->releasebuf = !0;
......
/* de4x5.c: A DIGITAL DE425/DE434/DE435/DE500 ethernet driver for Linux.
/* de4x5.c: A DIGITAL DE425/DE434/DE435/DE450/DE500 ethernet driver for Linux.
Copyright 1994, 1995 Digital Equipment Corporation.
......@@ -191,15 +191,25 @@
Fix bug in dc21040 and dc21041 autosense code.
Remove buffer copies on receive for Intels.
Change sk_buff handling during media disconnects to
eliminate DUP packets.
eliminate DUP packets.
Add dynamic TX thresholding.
Change all chips to use perfect multicast filtering.
Fix alloc_device() bug <jari@markkus2.fimr.fi>
0.43 21-Jun-96 Fix unconnected media TX retry bug.
Add Accton to the list of broken cards.
Fix TX under-run bug for non DC21140 chips.
Fix boot command probe bug in alloc_device() as
reported by <koen.gadeyne@barco.com> and
<orava@nether.tky.hut.fi>.
Add cache locks to prevent a race condition as
reported by <csd@microplex.com> and
<baba@beckman.uiuc.edu>.
Upgraded alloc_device() code.
=========================================================================
*/
static const char *version = "de4x5.c:v0.42 96/4/26 davies@wanton.lkg.dec.com\n";
static const char *version = "de4x5.c:v0.43 96/6/21 davies@wanton.lkg.dec.com\n";
#include <linux/module.h>
......@@ -226,6 +236,7 @@ static const char *version = "de4x5.c:v0.42 96/4/26 davies@wanton.lkg.dec.com\n"
#include <linux/time.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/ctype.h>
#include "de4x5.h"
......@@ -274,10 +285,12 @@ static struct phy_table phy_info[] = {
** Define special SROM detection cases
*/
static c_char enet_det[][ETH_ALEN] = {
{0x00, 0x00, 0xc0, 0x00, 0x00, 0x00}
{0x00, 0x00, 0xc0, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xe8, 0x00, 0x00, 0x00}
};
#define SMC 1
#define SMC 1
#define ACCTON 2
#ifdef DE4X5_DEBUG
......@@ -511,6 +524,7 @@ struct de4x5_private {
struct {
void *priv; /* Original kmalloc'd mem addr */
void *buf; /* Original kmalloc'd mem addr */
int lock; /* Lock the cache accesses */
s32 csr0; /* Saved Bus Mode Register */
s32 csr6; /* Saved Operating Mode Reg. */
s32 csr7; /* Saved IRQ Mask Register */
......@@ -633,12 +647,15 @@ static int get_hw_addr(struct device *dev);
static void eisa_probe(struct device *dev, u_long iobase);
static void pci_probe(struct device *dev, u_long iobase);
static struct device *alloc_device(struct device *dev, u_long iobase);
static struct device *insert_device(struct device *dev, u_long iobase,
int (*init)(struct device *));
static char *build_setup_frame(struct device *dev, int mode);
static void disable_ast(struct device *dev);
static void enable_ast(struct device *dev, u32 time_out);
static long de4x5_switch_to_srl(struct device *dev);
static long de4x5_switch_to_mii(struct device *dev);
static void timeout(struct device *dev, void (*fn)(u_long data), u_long data, u_long msec);
static int de4x5_dev_index(char *s);
static void de4x5_dbg_open(struct device *dev);
static void de4x5_dbg_mii(struct device *dev, int k);
static void de4x5_dbg_media(struct device *dev);
......@@ -683,7 +700,7 @@ de4x5_probe(struct device *dev)
{
int tmp = num_de4x5s, status = -ENODEV;
u_long iobase = dev->base_addr;
eisa_probe(dev, iobase);
pci_probe(dev, iobase);
......@@ -691,7 +708,7 @@ de4x5_probe(struct device *dev)
printk("%s: de4x5_probe() cannot find device at 0x%04lx.\n", dev->name,
iobase);
}
/*
** Walk the device list to check that at least one device
** initialised OK
......@@ -1076,6 +1093,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
return 0;
}
set_bit(0, (void*)&dev->tbusy); /* Stop send re-tries */
if (lp->tx_enable == NO) { /* Cannot send for now */
return -1;
}
......@@ -1085,11 +1103,13 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
** interrupts are lost by delayed descriptor status updates relative to
** the irq assertion, especially with a busy PCI bus.
*/
set_bit(0, (void*)&dev->tbusy);
cli();
de4x5_tx(dev);
sti();
/* Test if cache is already locked - requeue skb if so */
if (set_bit(0, (void *)&lp->cache.lock) && !dev->interrupt) return -1;
/* Transmit descriptor ring full or stale skb */
if (dev->tbusy || lp->tx_skb[lp->tx_new]) {
if (dev->interrupt) {
......@@ -1130,6 +1150,8 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
}
}
lp->cache.lock = 0;
return status;
}
......@@ -1195,8 +1217,11 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/* Load the TX ring with any locally stored packets */
while (lp->cache.skb && !dev->tbusy && lp->tx_enable) {
de4x5_queue_pkt(de4x5_get_cache(dev), dev);
if (!set_bit(0, (void *)&lp->cache.lock)) {
while (lp->cache.skb && !dev->tbusy && lp->tx_enable) {
de4x5_queue_pkt(de4x5_get_cache(dev), dev);
}
lp->cache.lock = 0;
}
dev->interrupt = UNMASK_INTERRUPTS;
......@@ -1376,7 +1401,7 @@ de4x5_txur(struct device *dev)
int omr;
omr = inl(DE4X5_OMR);
if (!(omr & OMR_SF)) {
if (!(omr & OMR_SF) || (lp->chipset==DC21041) || (lp->chipset==DC21040)) {
omr &= ~(OMR_ST|OMR_SR);
outl(omr, DE4X5_OMR);
while (inl(DE4X5_STS) & STS_TS);
......@@ -1564,6 +1589,7 @@ eisa_probe(struct device *dev, u_long ioaddr)
u_long iobase;
struct bus_type *lp = &bus;
char name[DE4X5_STRLEN];
struct device *tmp;
if (!ioaddr && autoprobed) return; /* Been here before ! */
......@@ -1589,15 +1615,14 @@ eisa_probe(struct device *dev, u_long ioaddr)
DevicePresent(EISA_APROM);
/* Write the PCI Configuration Registers */
outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
outl(0x00004000, PCI_CFLT);
outl(0x00006000, PCI_CFLT);
outl(iobase, PCI_CBIO);
if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) {
if ((status = de4x5_hw_init(dev, iobase)) == 0) {
if ((tmp = alloc_device(dev, iobase)) != NULL) {
if ((status = de4x5_hw_init(tmp, iobase)) == 0) {
num_de4x5s++;
}
num_eth++;
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04lx.\n", dev->name,iobase);
......@@ -1632,6 +1657,7 @@ pci_probe(struct device *dev, u_long ioaddr)
u_int class = DE4X5_CLASS_CODE;
u_int iobase;
struct bus_type *lp = &bus;
struct device *tmp;
if ((!ioaddr || !loading_module) && autoprobed) return;
......@@ -1639,14 +1665,14 @@ pci_probe(struct device *dev, u_long ioaddr)
lp->bus = PCI;
if (ioaddr < 0x1000) {
if ((ioaddr < 0x1000) && loading_module) {
pbus = (u_short)(ioaddr >> 8);
dnum = (u_short)(ioaddr & 0xff);
} else {
pbus = 0;
dnum = 0;
}
for (index=0;
(pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND);
index++) {
......@@ -1667,7 +1693,7 @@ pci_probe(struct device *dev, u_long ioaddr)
/* Get the board I/O address */
pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &iobase);
iobase &= CBIO_MASK;
/* Fetch the IRQ to be used */
pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &irq);
if ((irq == 0) || (irq == (u_char) 0xff)) continue;
......@@ -1684,12 +1710,11 @@ pci_probe(struct device *dev, u_long ioaddr)
DevicePresent(DE4X5_APROM);
if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) {
dev->irq = irq;
if ((status = de4x5_hw_init(dev, iobase)) == 0) {
if ((tmp = alloc_device(dev, iobase)) != NULL) {
tmp->irq = irq;
if ((status = de4x5_hw_init(tmp, iobase)) == 0) {
num_de4x5s++;
}
num_eth++;
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04x.\n", dev->name,
......@@ -1702,109 +1727,95 @@ pci_probe(struct device *dev, u_long ioaddr)
}
/*
** Allocate the device by pointing to the next available space in the
** device structure. Should one not be available, it is created.
** Search the entire 'eth' device list for a fixed probe. If a match isn't
** found then check for an autoprobe or unused device location. If they
** are not available then insert a new device structure at the end of
** the current list.
*/
static struct device *
alloc_device(struct device *dev, u_long iobase)
{
int addAutoProbe = 0;
struct device *tmp = NULL, *ret;
int (*init)(struct device *) = NULL;
struct device *adev = NULL;
int fixed = 0, new_dev = 0;
num_eth = de4x5_dev_index(dev->name);
if (loading_module) return dev;
/*
** Check the device structures for an end of list or unused device
*/
while (dev->next != NULL) {
if ((dev->base_addr == DE4X5_NDA) || (dev->base_addr == 0)) break;
dev = dev->next; /* walk through eth device list */
num_eth++; /* increment eth device number */
while (1) {
if (((dev->base_addr == DE4X5_NDA) || (dev->base_addr==0)) && !adev) {
adev=dev;
} else if ((dev->priv == NULL) && (dev->base_addr==iobase)) {
fixed = 1;
} else {
if (dev->next == NULL) {
new_dev = 1;
} else if (strncmp(dev->next->name, "eth", 3) != 0) {
new_dev = 1;
}
}
if ((dev->next == NULL) || new_dev || fixed) break;
dev = dev->next;
num_eth++;
}
/*
** If an autoprobe is requested for another device, we must re-insert
** the request later in the list. Remember the current position first.
*/
if ((dev->base_addr == 0) && (num_de4x5s > 0)) {
addAutoProbe++;
tmp = dev->next; /* point to the next device */
init = dev->init; /* remember the probe function */
if (adev && !fixed) {
dev = adev;
num_eth = de4x5_dev_index(dev->name);
new_dev = 0;
}
if (((dev->next == NULL) &&
((dev->base_addr != DE4X5_NDA) && (dev->base_addr != 0)) && !fixed) ||
new_dev) {
num_eth++; /* New device */
dev = insert_device(dev, iobase, de4x5_probe);
}
/*
** If at end of list and can't use current entry, malloc one up.
** If memory could not be allocated, print an error message.
*/
if ((dev->next == NULL) &&
!((dev->base_addr == DE4X5_NDA) || (dev->base_addr == 0))) {
dev->next = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL);
dev = dev->next; /* point to the new device */
if (dev == NULL) {
printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
return dev;
}
/*
** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message.
*/
static struct device *
insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
{
struct device *new;
new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL);
if (new == NULL) {
printk("eth%d: Device not initialised, insufficient memory\n",num_eth);
return NULL;
} else {
new->next = dev->next;
dev->next = new;
dev = dev->next; /* point to the new device */
dev->name = (char *)(dev + 1);
if (num_eth > 9999) {
sprintf(dev->name,"eth????");/* New device name */
} else {
/*
** If the memory was allocated, point to the new memory area
** and initialize it (name, I/O address, next device (NULL) and
** initialisation probe routine).
*/
dev->name = (char *)(dev + 1);
if (num_eth > 9999) {
sprintf(dev->name,"eth????");/* New device name */
} else {
sprintf(dev->name,"eth%d", num_eth);/* New device name */
}
dev->base_addr = iobase; /* assign the io address */
dev->next = NULL; /* mark the end of list */
dev->init = &de4x5_probe; /* initialisation routine */
num_de4x5s++;
sprintf(dev->name,"eth%d", num_eth);/* New device name */
}
dev->base_addr = iobase; /* assign the io address */
dev->init = init; /* initialisation routine */
}
ret = dev; /* return current struct, or NULL */
/*
** Now figure out what to do with the autoprobe that has to be inserted.
** Firstly, search the (possibly altered) list for an empty space.
*/
if (ret != NULL) {
if (addAutoProbe) {
for (; (tmp->next!=NULL) && (tmp->base_addr!=DE4X5_NDA); tmp=tmp->next);
/*
** If no more device structures and can't use the current one,
** malloc one up. If memory could not be allocated, print an error
**message.
*/
if ((tmp->next == NULL) && !(tmp->base_addr == DE4X5_NDA)) {
tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8,
GFP_KERNEL);
tmp = tmp->next; /* point to the new device */
if (tmp == NULL) {
printk("%s: Insufficient memory to extend the device list.\n",
dev->name);
} else {
/*
** If the memory was allocated, point to the new memory
** area and initialize it (name, I/O address, next device
** (NULL) and initialisation probe routine).
*/
tmp->name = (char *)(tmp + 1);
if (num_eth > 9999) {
sprintf(tmp->name,"eth????");
} else { /* New device name */
sprintf(tmp->name,"eth%d", num_eth);
}
tmp->base_addr = 0; /* re-insert the io address */
tmp->next = NULL; /* mark the end of list */
tmp->init = init; /* initialisation routine */
}
} else { /* structure already exists */
tmp->base_addr = 0; /* re-insert the io address */
}
}
return dev;
}
static int
de4x5_dev_index(char *s)
{
int i=0, j=0;
for (;*s; s++) {
if (isdigit(*s)) {
j=1;
i = (i * 10) + (*s - '0');
} else if (j) break;
}
return ret;
return i;
}
/*
......@@ -2381,8 +2392,10 @@ de4x5_init_connection(struct device *dev)
de4x5_setup_intr(dev);
lp->lostMedia = 0;
lp->tx_enable = YES;
dev->tbusy = 0;
sti();
outl(POLL_DEMAND, DE4X5_TPD);
mark_bh(NET_BH);
return;
}
......@@ -2643,8 +2656,9 @@ de4x5_alloc_rx_buff(struct device *dev, int index, int len)
ret = lp->rx_skb[index];
lp->rx_skb[index] = p;
if ((unsigned long) ret > 1)
skb_put(ret, len);
if ((u_long) ret > 1) {
skb_put(ret, len);
}
return ret;
......@@ -2675,7 +2689,7 @@ de4x5_free_rx_buffs(struct device *dev)
int i;
for (i=0; i<lp->rxRingSize; i++) {
if ((unsigned long) lp->rx_skb[i] > 1) {
if ((u_long) lp->rx_skb[i] > 1) {
dev_kfree_skb(lp->rx_skb[i], FREE_WRITE);
}
lp->rx_ring[i].status = 0;
......@@ -2728,7 +2742,6 @@ de4x5_save_skbs(struct device *dev)
de4x5_cache_state(dev, DE4X5_SAVE_STATE);
de4x5_sw_reset(dev);
de4x5_cache_state(dev, DE4X5_RESTORE_STATE);
dev->tbusy = 0;
lp->cache.save_cnt++;
START_DE4X5;
}
......@@ -2748,7 +2761,6 @@ de4x5_restore_skbs(struct device *dev)
de4x5_cache_state(dev, DE4X5_SAVE_STATE);
de4x5_sw_reset(dev);
de4x5_cache_state(dev, DE4X5_RESTORE_STATE);
dev->tbusy = 0;
lp->cache.save_cnt--;
START_DE4X5;
}
......@@ -3074,7 +3086,7 @@ get_hw_addr(struct device *dev)
} else if (!broken) {
dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
} else if (broken == SMC) { /* Assume SMC9332 for now */
} else if ((broken == SMC) || (broken == ACCTON)) {
dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
}
......@@ -3118,7 +3130,11 @@ de4x5_bad_srom(struct bus_type *lp)
for (i=0; i<sizeof(enet_det)/ETH_ALEN; i++) {
if (!de4x5_strncmp((char *)&lp->srom, (char *)&enet_det[i], 3) &&
!de4x5_strncmp((char *)&lp->srom+0x10, (char *)&enet_det[i], 3)) {
status = SMC;
if (i == 0) {
status = SMC;
} else if (i == 1) {
status = ACCTON;
}
break;
}
}
......@@ -4123,8 +4139,8 @@ cleanup_module(void)
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de4x5.c"
* compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
*
* compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de4x5.c"
* compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
* End:
*/
......@@ -20,6 +20,8 @@
Use dev_close cleanly so we always shut things down tidily.
Changed 29/10/95, Alan Cox to pass sockaddr's around for mac addresses.
14/06/96 - Paul Gortmaker: Add generic eth_change_mtu() function.
*/
#include <linux/config.h>
......@@ -144,6 +146,14 @@ static int eth_mac_addr(struct device *dev, void *p)
return 0;
}
static int eth_change_mtu(struct device *dev, int new_mtu)
{
if ((new_mtu < 68) || (new_mtu > 1500))
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
void ether_setup(struct device *dev)
{
int i;
......@@ -165,6 +175,7 @@ void ether_setup(struct device *dev)
}
}
dev->change_mtu = eth_change_mtu;
dev->hard_header = eth_header;
dev->rebuild_header = eth_rebuild_header;
dev->set_mac_address = eth_mac_addr;
......
......@@ -107,29 +107,27 @@ slhc_init(int rslots, int tslots)
memset(comp, 0, sizeof(struct slcompress));
if ( rslots > 0 && rslots < 256 ) {
comp->rstate =
(struct cstate *)kmalloc(rslots * sizeof(struct cstate),
GFP_KERNEL);
size_t rsize = rslots * sizeof(struct cstate);
comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
if (! comp->rstate)
{
kfree((unsigned char *)comp);
return NULL;
}
memset(comp->rstate, 0, rslots * sizeof(struct cstate));
memset(comp->rstate, 0, rsize);
comp->rslot_limit = rslots - 1;
}
if ( tslots > 0 && tslots < 256 ) {
comp->tstate =
(struct cstate *)kmalloc(tslots * sizeof(struct cstate),
GFP_KERNEL);
size_t tsize = tslots * sizeof(struct cstate);
comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
if (! comp->tstate)
{
kfree((unsigned char *)comp->rstate);
kfree((unsigned char *)comp);
return NULL;
}
memset(comp->tstate, 0, tslots * sizeof(struct cstate));
memset(comp->tstate, 0, tsize);
comp->tslot_limit = tslots - 1;
}
......
......@@ -49,7 +49,7 @@ char *version = "NET3 WIC version 0.9 hayes@netplumbing.com";
#include <asm/bitops.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <string.h>
#include <linux/string.h>
#define NET_DEBUG 1
/* Use 0 for production, 1 for verification, >2 for debug */
......
......@@ -48,9 +48,7 @@ dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONF
dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate 'Qlogic ISP SCSI support (EXPERIMENTAL)' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
fi
dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
fi
dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
......
This file contains brief information about the SCSI tape driver.
Last modified: Wed May 1 11:51:35 1996 by root@kai.makisara.fi
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
Last modified: Sun Jun 30 15:47:14 1996 by root@kai.makisara.fi
BASICS
......@@ -85,13 +88,15 @@ the SCSI adapter. The following buffering options are selectable at
compile time and/or at run time (via ioctl):
Buffering of data across write calls in fixed block mode (define
ST_BUFFER_WRITES). This should be disabled if reliable detection of
end of medium (EOM) for fixed block mode is desired.
ST_BUFFER_WRITES).
Asynchronous writing. Writing the buffer contents to the tape is
started and the write call returns immediately. The status is checked
at the next tape operation. Should not used if reliable EOM detection
is desired.
at the next tape operation.
Buffered writes and asynchronous writes may in some rare cases cause
problems in multivolume operations if there is not enough space after
the early-warning mark to flush the driver buffer.
Read ahead for fixed block mode (ST_READ_AHEAD). Filling the buffer is
attempted even if the user does not want to get all of the data at
......@@ -187,7 +192,8 @@ MTCOMPRESSION Sets compressing or uncompressing drive mode using the
control of compression. Some drives (like the Exabytes) use
density codes for compression control. Some drives use another
mode page but this page has not been implemented in the
driver.
driver. Some drives without compression capability will accept
any compression mode without error.
MTSETPART Moves the tape to the partition given by the argument at the
next tape operation. The block at which the tape is positioned
is the block where the tape was previously positioned in the
......@@ -310,5 +316,3 @@ within file can be obtained if ST_IN_FILE_POS is defined at compile
time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl.
(The driver always backs over a filemark crossed by read ahead if the
user does not request data that far.)
Kai M{kisara
......@@ -244,7 +244,7 @@ struct Scsi_Host
unsigned short extra_bytes;
volatile unsigned char host_busy;
char host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
int last_reset;
unsigned long last_reset;
struct wait_queue *host_wait;
Scsi_Cmnd *host_queue;
Scsi_Host_Template * hostt;
......
This diff is collapsed.
......@@ -43,6 +43,21 @@
#ifndef _QLOGICISP_H
#define _QLOGICISP_H
/*
* With the qlogic interface, every queue slot can hold a SCSI
* command with up to 4 scatter/gather entries. If we need more
* than 4 entries, continuation entries can be used that hold
* another 7 entries each. Unlike for other drivers, this means
* that the maximum number of scatter/gather entries we can
* support at any given time is a function of the number of queue
* slots available. That is, host->can_queue and host->sg_tablesize
* are dynamic and _not_ independent. This all works fine because
* requests are queued serially and the scatter/gather limit is
* determined for each queue request anew.
*/
#define QLOGICISP_REQ_QUEUE_LEN 63 /* must be power of two - 1 */
#define QLOGICISP_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0)
int isp1020_detect(Scsi_Host_Template *);
int isp1020_release(struct Scsi_Host *);
const char * isp1020_info(struct Scsi_Host *);
......@@ -57,28 +72,28 @@ int isp1020_biosparam(Disk *, kdev_t, int[]);
extern struct proc_dir_entry proc_scsi_isp1020;
#define QLOGICISP { \
/* next */ NULL, \
/* usage_count */ NULL, \
/* proc dir */ NULL, \
/* procfs info */ NULL, \
/* name */ NULL, \
/* detect */ isp1020_detect, \
/* release */ isp1020_release, \
/* info */ isp1020_info, \
/* command */ NULL, \
/* queuecommand */ isp1020_queuecommand, \
/* abort */ isp1020_abort, \
/* reset */ isp1020_reset, \
/* slave_attach */ NULL, \
/* bios_param */ isp1020_biosparam, \
/* can_queue */ 8, \
/* this_id */ -1, \
/* sg_tablesize */ 4, \
/* cmd_per_lun */ 1, \
/* present */ 0, \
/* unchecked_isa_dma */ 0, \
/* use_clustering */ DISABLE_CLUSTERING \
#define QLOGICISP { \
/* next */ NULL, \
/* usage_count */ NULL, \
/* proc dir */ NULL, \
/* procfs info */ NULL, \
/* name */ NULL, \
/* detect */ isp1020_detect, \
/* release */ isp1020_release, \
/* info */ isp1020_info, \
/* command */ NULL, \
/* queuecommand */ isp1020_queuecommand, \
/* abort */ isp1020_abort, \
/* reset */ isp1020_reset, \
/* slave_attach */ NULL, \
/* bios_param */ isp1020_biosparam, \
/* can_queue */ QLOGICISP_REQ_QUEUE_LEN, \
/* this_id */ -1, \
/* sg_tablesize */ QLOGICISP_MAX_SG(QLOGICISP_REQ_QUEUE_LEN), \
/* cmd_per_lun */ 1, \
/* present */ 0, \
/* unchecked_isa_dma */ 0, \
/* use_clustering */ DISABLE_CLUSTERING \
}
#endif /* _QLOGICISP_H */
......@@ -1184,27 +1184,38 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device,
inline void internal_cmnd (Scsi_Cmnd * SCpnt)
{
int temp;
unsigned long flags, timeout;
struct Scsi_Host * host;
unsigned int flags;
#ifdef DEBUG_DELAY
int clock;
unsigned long clock;
#endif
host = SCpnt->host;
/*
* We will wait MIN_RESET_DELAY clock ticks after the last reset so
* we can avoid the drive not being ready.
*/
save_flags(flags);
cli();
/* Assign a unique nonzero serial_number. */
if (++serial_number == 0) serial_number = 1;
SCpnt->serial_number = serial_number;
sti();
temp = host->last_reset + MIN_RESET_DELAY;
while (jiffies < temp);
/*
* We will wait MIN_RESET_DELAY clock ticks after the last reset so
* we can avoid the drive not being ready.
*/
timeout = host->last_reset + MIN_RESET_DELAY;
if (jiffies < timeout) {
/*
* NOTE: This may be executed from within an interrupt
* handler! This is bad, but for now, it'll do. The irq
* level of the interrupt handler has been masked out by the
* platform dependent interrupt handling code already, so the
* sti() here will not cause another call to the SCSI host's
* interrupt handler (assuming there is one irq-level per
* host).
*/
sti();
while (jiffies < timeout) barrier();
}
restore_flags(flags);
update_timeout(SCpnt, SCpnt->timeout_per_command);
......@@ -1245,15 +1256,16 @@ inline void internal_cmnd (Scsi_Cmnd * SCpnt)
}
else
{
int temp;
#ifdef DEBUG
printk("command() : routine at %p\n", host->hostt->command);
#endif
temp=host->hostt->command (SCpnt);
temp = host->hostt->command (SCpnt);
SCpnt->result = temp;
#ifdef DEBUG_DELAY
clock = jiffies + 4 * HZ;
while (jiffies < clock);
while (jiffies < clock) barrier();
printk("done(host = %d, result = %04x) : routine at %p\n",
host->host_no, temp, host->hostt->command);
#endif
......@@ -2055,10 +2067,11 @@ int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
* Protect against races here. If the command is done, or we are
* on a different command forget it.
*/
if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
if (reset_flags & SCSI_RESET_ASYNCHRONOUS)
if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
restore_flags(flags);
return 0;
}
}
if (SCpnt->internal_timeout & IN_RESET)
{
......
......@@ -202,7 +202,7 @@ typedef struct scsi_device {
* Use these to separate status msg and our bytes
*/
#define status_byte(result) (((result) >> 1) & 0xf)
#define status_byte(result) (((result) >> 1) & 0x1f)
#define msg_byte(result) (((result) >> 8) & 0xff)
#define host_byte(result) (((result) >> 16) & 0xff)
#define driver_byte(result) (((result) >> 24) & 0xff)
......
......@@ -230,7 +230,7 @@ static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
* Now copy the result back to the user buffer.
*/
device->header.pack_len=device->header.reply_len;
device->header.result=0;
if (count>=sizeof(struct sg_header))
{
memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
......@@ -242,7 +242,7 @@ static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
}
}
else
count=0;
count= device->header.result==0 ? 0 : -EIO;
/*
* Clean up, and release the device so that we can send another
......@@ -276,12 +276,7 @@ static void sg_command_done(Scsi_Cmnd * SCpnt)
* wrong.
*/
memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
if (SCpnt->sense_buffer[0])
{
device->header.result=EIO;
}
else
device->header.result=SCpnt->result;
device->header.result=SCpnt->result;
/*
* Now wake up the process that is waiting for the
......@@ -593,6 +588,11 @@ static void sg_detach(Scsi_Device * SDp)
gpnt->device = NULL;
SDp->attached--;
sg_template.nr_dev--;
/*
* avoid associated device /dev/sg? bying incremented
* each time module is inserted/removed , <dan@lectra.fr>
*/
sg_template.dev_noticed--;
return;
}
return;
......
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