aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aha152x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aha152x.c')
-rw-r--r--drivers/scsi/aha152x.c100
1 files changed, 58 insertions, 42 deletions
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index de80cdfb5b9d..fb6a476eb873 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -253,6 +253,7 @@
253#include <linux/isapnp.h> 253#include <linux/isapnp.h>
254#include <linux/spinlock.h> 254#include <linux/spinlock.h>
255#include <linux/workqueue.h> 255#include <linux/workqueue.h>
256#include <linux/list.h>
256#include <asm/semaphore.h> 257#include <asm/semaphore.h>
257#include <scsi/scsicam.h> 258#include <scsi/scsicam.h>
258 259
@@ -262,6 +263,8 @@
262#include <scsi/scsi_transport_spi.h> 263#include <scsi/scsi_transport_spi.h>
263#include "aha152x.h" 264#include "aha152x.h"
264 265
266static LIST_HEAD(aha152x_host_list);
267
265 268
266/* DEFINES */ 269/* DEFINES */
267 270
@@ -423,8 +426,6 @@ MODULE_DEVICE_TABLE(isapnp, id_table);
423 426
424#endif /* !PCMCIA */ 427#endif /* !PCMCIA */
425 428
426static int registered_count=0;
427static struct Scsi_Host *aha152x_host[2];
428static struct scsi_host_template aha152x_driver_template; 429static struct scsi_host_template aha152x_driver_template;
429 430
430/* 431/*
@@ -541,6 +542,7 @@ struct aha152x_hostdata {
541#ifdef __ISAPNP__ 542#ifdef __ISAPNP__
542 struct pnp_dev *pnpdev; 543 struct pnp_dev *pnpdev;
543#endif 544#endif
545 struct list_head host_list;
544}; 546};
545 547
546 548
@@ -551,6 +553,11 @@ struct aha152x_hostdata {
551struct aha152x_scdata { 553struct aha152x_scdata {
552 Scsi_Cmnd *next; /* next sc in queue */ 554 Scsi_Cmnd *next; /* next sc in queue */
553 struct semaphore *sem; /* semaphore to block on */ 555 struct semaphore *sem; /* semaphore to block on */
556 unsigned char cmd_len;
557 unsigned char cmnd[MAX_COMMAND_SIZE];
558 unsigned short use_sg;
559 unsigned request_bufflen;
560 void *request_buffer;
554}; 561};
555 562
556 563
@@ -750,20 +757,9 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp)
750 return ptr; 757 return ptr;
751} 758}
752 759
753static inline struct Scsi_Host *lookup_irq(int irqno)
754{
755 int i;
756
757 for(i=0; i<ARRAY_SIZE(aha152x_host); i++)
758 if(aha152x_host[i] && aha152x_host[i]->irq==irqno)
759 return aha152x_host[i];
760
761 return NULL;
762}
763
764static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs) 760static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
765{ 761{
766 struct Scsi_Host *shpnt = lookup_irq(irqno); 762 struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
767 763
768 if (!shpnt) { 764 if (!shpnt) {
769 printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); 765 printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
@@ -786,10 +782,11 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
786 return NULL; 782 return NULL;
787 } 783 }
788 784
789 /* need to have host registered before triggering any interrupt */
790 aha152x_host[registered_count] = shpnt;
791
792 memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt)); 785 memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
786 INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
787
788 /* need to have host registered before triggering any interrupt */
789 list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list);
793 790
794 shpnt->io_port = setup->io_port; 791 shpnt->io_port = setup->io_port;
795 shpnt->n_io_port = IO_RANGE; 792 shpnt->n_io_port = IO_RANGE;
@@ -855,7 +852,7 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
855 SETPORT(SIMODE0, 0); 852 SETPORT(SIMODE0, 0);
856 SETPORT(SIMODE1, 0); 853 SETPORT(SIMODE1, 0);
857 854
858 if( request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { 855 if( request_irq(shpnt->irq, swintr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) {
859 printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq); 856 printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
860 goto out_host_put; 857 goto out_host_put;
861 } 858 }
@@ -889,7 +886,7 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
889 SETPORT(SSTAT0, 0x7f); 886 SETPORT(SSTAT0, 0x7f);
890 SETPORT(SSTAT1, 0xef); 887 SETPORT(SSTAT1, 0xef);
891 888
892 if ( request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { 889 if ( request_irq(shpnt->irq, intr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) {
893 printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq); 890 printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
894 goto out_host_put; 891 goto out_host_put;
895 } 892 }
@@ -902,12 +899,10 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
902 899
903 scsi_scan_host(shpnt); 900 scsi_scan_host(shpnt);
904 901
905 registered_count++;
906
907 return shpnt; 902 return shpnt;
908 903
909out_host_put: 904out_host_put:
910 aha152x_host[registered_count]=NULL; 905 list_del(&HOSTDATA(shpnt)->host_list);
911 scsi_host_put(shpnt); 906 scsi_host_put(shpnt);
912 907
913 return NULL; 908 return NULL;
@@ -932,6 +927,7 @@ void aha152x_release(struct Scsi_Host *shpnt)
932#endif 927#endif
933 928
934 scsi_remove_host(shpnt); 929 scsi_remove_host(shpnt);
930 list_del(&HOSTDATA(shpnt)->host_list);
935 scsi_host_put(shpnt); 931 scsi_host_put(shpnt);
936} 932}
937 933
@@ -1006,11 +1002,20 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p
1006 return FAILED; 1002 return FAILED;
1007 } 1003 }
1008 } else { 1004 } else {
1005 struct aha152x_scdata *sc;
1006
1009 SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); 1007 SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
1010 if(SCpnt->host_scribble==0) { 1008 if(SCpnt->host_scribble==0) {
1011 printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); 1009 printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
1012 return FAILED; 1010 return FAILED;
1013 } 1011 }
1012
1013 sc = SCDATA(SCpnt);
1014 memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd));
1015 sc->request_buffer = SCpnt->request_buffer;
1016 sc->request_bufflen = SCpnt->request_bufflen;
1017 sc->use_sg = SCpnt->use_sg;
1018 sc->cmd_len = SCpnt->cmd_len;
1014 } 1019 }
1015 1020
1016 SCNEXT(SCpnt) = NULL; 1021 SCNEXT(SCpnt) = NULL;
@@ -1165,6 +1170,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
1165 DECLARE_MUTEX_LOCKED(sem); 1170 DECLARE_MUTEX_LOCKED(sem);
1166 struct timer_list timer; 1171 struct timer_list timer;
1167 int ret, issued, disconnected; 1172 int ret, issued, disconnected;
1173 unsigned char old_cmd_len = SCpnt->cmd_len;
1174 unsigned short old_use_sg = SCpnt->use_sg;
1175 void *old_buffer = SCpnt->request_buffer;
1176 unsigned old_bufflen = SCpnt->request_bufflen;
1168 unsigned long flags; 1177 unsigned long flags;
1169 1178
1170#if defined(AHA152X_DEBUG) 1179#if defined(AHA152X_DEBUG)
@@ -1198,11 +1207,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
1198 add_timer(&timer); 1207 add_timer(&timer);
1199 down(&sem); 1208 down(&sem);
1200 del_timer(&timer); 1209 del_timer(&timer);
1201 1210
1202 SCpnt->cmd_len = SCpnt->old_cmd_len; 1211 SCpnt->cmd_len = old_cmd_len;
1203 SCpnt->use_sg = SCpnt->old_use_sg; 1212 SCpnt->use_sg = old_use_sg;
1204 SCpnt->request_buffer = SCpnt->buffer; 1213 SCpnt->request_buffer = old_buffer;
1205 SCpnt->request_bufflen = SCpnt->bufflen; 1214 SCpnt->request_bufflen = old_bufflen;
1206 1215
1207 DO_LOCK(flags); 1216 DO_LOCK(flags);
1208 1217
@@ -1441,9 +1450,12 @@ static struct work_struct aha152x_tq;
1441 */ 1450 */
1442static void run(void) 1451static void run(void)
1443{ 1452{
1444 int i; 1453 struct aha152x_hostdata *hd;
1445 for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) { 1454
1446 is_complete(aha152x_host[i]); 1455 list_for_each_entry(hd, &aha152x_host_list, host_list) {
1456 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
1457
1458 is_complete(shost);
1447 } 1459 }
1448} 1460}
1449 1461
@@ -1453,7 +1465,7 @@ static void run(void)
1453 */ 1465 */
1454static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) 1466static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
1455{ 1467{
1456 struct Scsi_Host *shpnt = lookup_irq(irqno); 1468 struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
1457 unsigned long flags; 1469 unsigned long flags;
1458 unsigned char rev, dmacntrl0; 1470 unsigned char rev, dmacntrl0;
1459 1471
@@ -1565,6 +1577,9 @@ static void busfree_run(struct Scsi_Host *shpnt)
1565#endif 1577#endif
1566 1578
1567 if(DONE_SC->SCp.phase & check_condition) { 1579 if(DONE_SC->SCp.phase & check_condition) {
1580 struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
1581 struct aha152x_scdata *sc = SCDATA(cmd);
1582
1568#if 0 1583#if 0
1569 if(HOSTDATA(shpnt)->debug & debug_eh) { 1584 if(HOSTDATA(shpnt)->debug & debug_eh) {
1570 printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC)); 1585 printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
@@ -1573,13 +1588,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
1573#endif 1588#endif
1574 1589
1575 /* restore old command */ 1590 /* restore old command */
1576 memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd)); 1591 memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd));
1577 DONE_SC->request_buffer = DONE_SC->buffer; 1592 cmd->request_buffer = sc->request_buffer;
1578 DONE_SC->request_bufflen = DONE_SC->bufflen; 1593 cmd->request_bufflen = sc->request_bufflen;
1579 DONE_SC->use_sg = DONE_SC->old_use_sg; 1594 cmd->use_sg = sc->use_sg;
1580 DONE_SC->cmd_len = DONE_SC->old_cmd_len; 1595 cmd->cmd_len = sc->cmd_len;
1581 1596
1582 DONE_SC->SCp.Status = 0x02; 1597 cmd->SCp.Status = 0x02;
1583 1598
1584 HOSTDATA(shpnt)->commands--; 1599 HOSTDATA(shpnt)->commands--;
1585 if (!HOSTDATA(shpnt)->commands) 1600 if (!HOSTDATA(shpnt)->commands)
@@ -3932,16 +3947,17 @@ static int __init aha152x_init(void)
3932#endif 3947#endif
3933 } 3948 }
3934 3949
3935 return registered_count>0; 3950 return 1;
3936} 3951}
3937 3952
3938static void __exit aha152x_exit(void) 3953static void __exit aha152x_exit(void)
3939{ 3954{
3940 int i; 3955 struct aha152x_hostdata *hd;
3956
3957 list_for_each_entry(hd, &aha152x_host_list, host_list) {
3958 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
3941 3959
3942 for(i=0; i<ARRAY_SIZE(setup); i++) { 3960 aha152x_release(shost);
3943 aha152x_release(aha152x_host[i]);
3944 aha152x_host[i]=NULL;
3945 } 3961 }
3946} 3962}
3947 3963