aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/esp.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-06-23 20:29:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-24 02:15:54 -0400
commit411aa5540536feace62c97478a8ea5dab7469377 (patch)
tree7aef2cb7f15734027d8f88b96826692e57f3fc94 /drivers/scsi/esp.c
parent69b5c4f18b2ceab3da9e854d02f8d9a2aa5b8431 (diff)
[SCSI] sparc: Port esp to new SBUS driver layer.
This also turns the driver into a new-style scsi driver. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/scsi/esp.c')
-rw-r--r--drivers/scsi/esp.c318
1 files changed, 157 insertions, 161 deletions
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 0a3e45d7a972..8e8fc43c1d22 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,7 +1,6 @@
1/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $ 1/* esp.c: ESP Sun SCSI driver.
2 * esp.c: EnhancedScsiProcessor Sun SCSI driver code.
3 * 2 *
4 * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) 3 * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net)
5 */ 4 */
6 5
7/* TODO: 6/* TODO:
@@ -185,11 +184,6 @@ enum {
185/*5*/ do_intr_end 184/*5*/ do_intr_end
186}; 185};
187 186
188/* The master ring of all esp hosts we are managing in this driver. */
189static struct esp *espchain;
190static DEFINE_SPINLOCK(espchain_lock);
191static int esps_running = 0;
192
193/* Forward declarations. */ 187/* Forward declarations. */
194static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs); 188static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
195 189
@@ -694,36 +688,6 @@ static void __init esp_bootup_reset(struct esp *esp)
694 sbus_readb(esp->eregs + ESP_INTRPT); 688 sbus_readb(esp->eregs + ESP_INTRPT);
695} 689}
696 690
697static void esp_chain_add(struct esp *esp)
698{
699 spin_lock_irq(&espchain_lock);
700 if (espchain) {
701 struct esp *elink = espchain;
702 while (elink->next)
703 elink = elink->next;
704 elink->next = esp;
705 } else {
706 espchain = esp;
707 }
708 esp->next = NULL;
709 spin_unlock_irq(&espchain_lock);
710}
711
712static void esp_chain_del(struct esp *esp)
713{
714 spin_lock_irq(&espchain_lock);
715 if (espchain == esp) {
716 espchain = esp->next;
717 } else {
718 struct esp *elink = espchain;
719 while (elink->next != esp)
720 elink = elink->next;
721 elink->next = esp->next;
722 }
723 esp->next = NULL;
724 spin_unlock_irq(&espchain_lock);
725}
726
727static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev) 691static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev)
728{ 692{
729 struct sbus_dev *sdev = esp->sdev; 693 struct sbus_dev *sdev = esp->sdev;
@@ -830,19 +794,20 @@ static int __init esp_register_irq(struct esp *esp)
830static void __init esp_get_scsi_id(struct esp *esp) 794static void __init esp_get_scsi_id(struct esp *esp)
831{ 795{
832 struct sbus_dev *sdev = esp->sdev; 796 struct sbus_dev *sdev = esp->sdev;
797 struct device_node *dp = sdev->ofdev.node;
833 798
834 esp->scsi_id = prom_getintdefault(esp->prom_node, 799 esp->scsi_id = of_getintprop_default(dp,
835 "initiator-id", 800 "initiator-id",
836 -1); 801 -1);
837 if (esp->scsi_id == -1) 802 if (esp->scsi_id == -1)
838 esp->scsi_id = prom_getintdefault(esp->prom_node, 803 esp->scsi_id = of_getintprop_default(dp,
839 "scsi-initiator-id", 804 "scsi-initiator-id",
840 -1); 805 -1);
841 if (esp->scsi_id == -1) 806 if (esp->scsi_id == -1)
842 esp->scsi_id = (sdev->bus == NULL) ? 7 : 807 esp->scsi_id = (sdev->bus == NULL) ? 7 :
843 prom_getintdefault(sdev->bus->prom_node, 808 of_getintprop_default(sdev->bus->ofdev.node,
844 "scsi-initiator-id", 809 "scsi-initiator-id",
845 7); 810 7);
846 esp->ehost->this_id = esp->scsi_id; 811 esp->ehost->this_id = esp->scsi_id;
847 esp->scsi_id_mask = (1 << esp->scsi_id); 812 esp->scsi_id_mask = (1 << esp->scsi_id);
848 813
@@ -1067,28 +1032,30 @@ static void __init esp_init_swstate(struct esp *esp)
1067 esp->prev_hme_dmacsr = 0xffffffff; 1032 esp->prev_hme_dmacsr = 0xffffffff;
1068} 1033}
1069 1034
1070static int __init detect_one_esp(struct scsi_host_template *tpnt, struct sbus_dev *esp_dev, 1035static int __init detect_one_esp(struct scsi_host_template *tpnt,
1071 struct sbus_dev *espdma, struct sbus_bus *sbus, 1036 struct device *dev,
1072 int id, int hme) 1037 struct sbus_dev *esp_dev,
1038 struct sbus_dev *espdma,
1039 struct sbus_bus *sbus,
1040 int hme)
1073{ 1041{
1074 struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp)); 1042 static int instance;
1043 struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp));
1075 struct esp *esp; 1044 struct esp *esp;
1076 1045
1077 if (!esp_host) { 1046 if (!esp_host)
1078 printk("ESP: Cannot register SCSI host\n"); 1047 return -ENOMEM;
1079 return -1; 1048
1080 }
1081 if (hme) 1049 if (hme)
1082 esp_host->max_id = 16; 1050 esp_host->max_id = 16;
1083 esp = (struct esp *) esp_host->hostdata; 1051 esp = (struct esp *) esp_host->hostdata;
1084 esp->ehost = esp_host; 1052 esp->ehost = esp_host;
1085 esp->sdev = esp_dev; 1053 esp->sdev = esp_dev;
1086 esp->esp_id = id; 1054 esp->esp_id = instance;
1087 esp->prom_node = esp_dev->prom_node; 1055 esp->prom_node = esp_dev->prom_node;
1088 prom_getstring(esp->prom_node, "name", esp->prom_name, 1056 prom_getstring(esp->prom_node, "name", esp->prom_name,
1089 sizeof(esp->prom_name)); 1057 sizeof(esp->prom_name));
1090 1058
1091 esp_chain_add(esp);
1092 if (esp_find_dvma(esp, espdma) < 0) 1059 if (esp_find_dvma(esp, espdma) < 0)
1093 goto fail_unlink; 1060 goto fail_unlink;
1094 if (esp_map_regs(esp, hme) < 0) { 1061 if (esp_map_regs(esp, hme) < 0) {
@@ -1115,8 +1082,19 @@ static int __init detect_one_esp(struct scsi_host_template *tpnt, struct sbus_de
1115 1082
1116 esp_bootup_reset(esp); 1083 esp_bootup_reset(esp);
1117 1084
1085 if (scsi_add_host(esp_host, dev))
1086 goto fail_free_irq;
1087
1088 dev_set_drvdata(&esp_dev->ofdev.dev, esp);
1089
1090 scsi_scan_host(esp_host);
1091 instance++;
1092
1118 return 0; 1093 return 0;
1119 1094
1095fail_free_irq:
1096 free_irq(esp->ehost->irq, esp);
1097
1120fail_unmap_cmdarea: 1098fail_unmap_cmdarea:
1121 sbus_free_consistent(esp->sdev, 16, 1099 sbus_free_consistent(esp->sdev, 16,
1122 (void *) esp->esp_command, 1100 (void *) esp->esp_command,
@@ -1129,119 +1107,101 @@ fail_dvma_release:
1129 esp->dma->allocated = 0; 1107 esp->dma->allocated = 0;
1130 1108
1131fail_unlink: 1109fail_unlink:
1132 esp_chain_del(esp); 1110 scsi_host_put(esp_host);
1133 scsi_unregister(esp_host);
1134 return -1; 1111 return -1;
1135} 1112}
1136 1113
1137/* Detecting ESP chips on the machine. This is the simple and easy 1114/* Detecting ESP chips on the machine. This is the simple and easy
1138 * version. 1115 * version.
1139 */ 1116 */
1117static int __devexit esp_remove_common(struct esp *esp)
1118{
1119 unsigned int irq = esp->ehost->irq;
1120
1121 scsi_remove_host(esp->ehost);
1122
1123 scsi_host_put(esp->ehost);
1124 esp->ehost = NULL;
1125
1126 ESP_INTSOFF(esp->dregs);
1127#if 0
1128 esp_reset_dma(esp);
1129 esp_reset_esp(esp);
1130#endif
1131
1132 free_irq(irq, esp);
1133 sbus_free_consistent(esp->sdev, 16,
1134 (void *) esp->esp_command, esp->esp_command_dvma);
1135 sbus_iounmap(esp->eregs, ESP_REG_SIZE);
1136 esp->dma->allocated = 0;
1137
1138 kfree(esp);
1139
1140 return 0;
1141}
1142
1140 1143
1141#ifdef CONFIG_SUN4 1144#ifdef CONFIG_SUN4
1142 1145
1143#include <asm/sun4paddr.h> 1146#include <asm/sun4paddr.h>
1144 1147
1145static int __init esp_detect(struct scsi_host_template *tpnt) 1148static struct sbus_dev sun4_esp_dev;
1146{
1147 static struct sbus_dev esp_dev;
1148 int esps_in_use = 0;
1149
1150 espchain = NULL;
1151 1149
1150static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
1151{
1152 if (sun4_esp_physaddr) { 1152 if (sun4_esp_physaddr) {
1153 memset (&esp_dev, 0, sizeof(esp_dev)); 1153 memset(&sun4_esp_dev, 0, sizeof(esp_dev));
1154 esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; 1154 sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
1155 esp_dev.irqs[0] = 4; 1155 sun4_esp_dev.irqs[0] = 4;
1156 esp_dev.resource[0].start = sun4_esp_physaddr; 1156 sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
1157 esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1; 1157 sun4_esp_dev.resource[0].end =
1158 esp_dev.resource[0].flags = IORESOURCE_IO; 1158 sun4_esp_physaddr + ESP_REG_SIZE - 1;
1159 1159 sun4_esp_dev.resource[0].flags = IORESOURCE_IO;
1160 if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) 1160
1161 esps_in_use++; 1161 return detect_one_esp(tpnt, NULL,
1162 printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); 1162 &sun4_esp_dev, NULL, NULL, 0);
1163 esps_running = esps_in_use;
1164 } 1163 }
1165 return esps_in_use; 1164 return 0;
1166} 1165}
1167 1166
1168#else /* !CONFIG_SUN4 */ 1167static int __devexit esp_sun4_remove(void)
1169
1170static int __init esp_detect(struct scsi_host_template *tpnt)
1171{ 1168{
1172 struct sbus_bus *sbus; 1169 struct esp *esp = dev_get_drvdata(&dev->dev);
1173 struct sbus_dev *esp_dev, *sbdev_iter;
1174 int nesps = 0, esps_in_use = 0;
1175 1170
1176 espchain = 0; 1171 return esp_remove_common(esp);
1177 if (!sbus_root) {
1178#ifdef CONFIG_PCI
1179 return 0;
1180#else
1181 panic("No SBUS in esp_detect()");
1182#endif
1183 }
1184 for_each_sbus(sbus) {
1185 for_each_sbusdev(sbdev_iter, sbus) {
1186 struct sbus_dev *espdma = NULL;
1187 int hme = 0;
1188
1189 /* Is it an esp sbus device? */
1190 esp_dev = sbdev_iter;
1191 if (strcmp(esp_dev->prom_name, "esp") &&
1192 strcmp(esp_dev->prom_name, "SUNW,esp")) {
1193 if (!strcmp(esp_dev->prom_name, "SUNW,fas")) {
1194 hme = 1;
1195 espdma = esp_dev;
1196 } else {
1197 if (!esp_dev->child ||
1198 (strcmp(esp_dev->prom_name, "espdma") &&
1199 strcmp(esp_dev->prom_name, "dma")))
1200 continue; /* nope... */
1201 espdma = esp_dev;
1202 esp_dev = esp_dev->child;
1203 if (strcmp(esp_dev->prom_name, "esp") &&
1204 strcmp(esp_dev->prom_name, "SUNW,esp"))
1205 continue; /* how can this happen? */
1206 }
1207 }
1208
1209 if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)
1210 continue;
1211
1212 esps_in_use++;
1213 } /* for each sbusdev */
1214 } /* for each sbus */
1215 printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
1216 esps_in_use);
1217 esps_running = esps_in_use;
1218 return esps_in_use;
1219} 1172}
1220 1173
1221#endif /* !CONFIG_SUN4 */ 1174#else /* !CONFIG_SUN4 */
1222 1175
1223/* 1176static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
1224 */
1225static int esp_release(struct Scsi_Host *host)
1226{ 1177{
1227 struct esp *esp = (struct esp *) host->hostdata; 1178 struct sbus_dev *sdev = to_sbus_device(&dev->dev);
1179 struct device_node *dp = dev->node;
1180 struct sbus_dev *dma_sdev = NULL;
1181 int hme = 0;
1182
1183 if (dp->parent &&
1184 (!strcmp(dp->parent->name, "espdma") ||
1185 !strcmp(dp->parent->name, "dma")))
1186 dma_sdev = sdev->parent;
1187 else if (!strcmp(dp->name, "SUNW,fas")) {
1188 dma_sdev = sdev;
1189 hme = 1;
1190 }
1228 1191
1229 ESP_INTSOFF(esp->dregs); 1192 return detect_one_esp(match->data, &dev->dev,
1230#if 0 1193 sdev, dma_sdev, sdev->bus, hme);
1231 esp_reset_dma(esp); 1194}
1232 esp_reset_esp(esp);
1233#endif
1234 1195
1235 free_irq(esp->ehost->irq, esp); 1196static int __devexit esp_sbus_remove(struct of_device *dev)
1236 sbus_free_consistent(esp->sdev, 16, 1197{
1237 (void *) esp->esp_command, esp->esp_command_dvma); 1198 struct esp *esp = dev_get_drvdata(&dev->dev);
1238 sbus_iounmap(esp->eregs, ESP_REG_SIZE);
1239 esp->dma->allocated = 0;
1240 esp_chain_del(esp);
1241 1199
1242 return 0; 1200 return esp_remove_common(esp);
1243} 1201}
1244 1202
1203#endif /* !CONFIG_SUN4 */
1204
1245/* The info function will return whatever useful 1205/* The info function will return whatever useful
1246 * information the developer sees fit. If not provided, then 1206 * information the developer sees fit. If not provided, then
1247 * the name field will be used instead. 1207 * the name field will be used instead.
@@ -1415,18 +1375,11 @@ static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len)
1415static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, 1375static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1416 int length, int inout) 1376 int length, int inout)
1417{ 1377{
1418 struct esp *esp; 1378 struct esp *esp = (struct esp *) host->hostdata;
1419 1379
1420 if (inout) 1380 if (inout)
1421 return -EINVAL; /* not yet */ 1381 return -EINVAL; /* not yet */
1422 1382
1423 for_each_esp(esp) {
1424 if (esp->ehost == host)
1425 break;
1426 }
1427 if (!esp)
1428 return -EINVAL;
1429
1430 if (start) 1383 if (start)
1431 *start = buffer; 1384 *start = buffer;
1432 1385
@@ -4377,15 +4330,12 @@ static void esp_slave_destroy(struct scsi_device *SDptr)
4377 SDptr->hostdata = NULL; 4330 SDptr->hostdata = NULL;
4378} 4331}
4379 4332
4380static struct scsi_host_template driver_template = { 4333static struct scsi_host_template esp_template = {
4381 .proc_name = "esp", 4334 .module = THIS_MODULE,
4382 .proc_info = esp_proc_info, 4335 .name = "esp",
4383 .name = "Sun ESP 100/100a/200", 4336 .info = esp_info,
4384 .detect = esp_detect,
4385 .slave_alloc = esp_slave_alloc, 4337 .slave_alloc = esp_slave_alloc,
4386 .slave_destroy = esp_slave_destroy, 4338 .slave_destroy = esp_slave_destroy,
4387 .release = esp_release,
4388 .info = esp_info,
4389 .queuecommand = esp_queue, 4339 .queuecommand = esp_queue,
4390 .eh_abort_handler = esp_abort, 4340 .eh_abort_handler = esp_abort,
4391 .eh_bus_reset_handler = esp_reset, 4341 .eh_bus_reset_handler = esp_reset,
@@ -4394,12 +4344,58 @@ static struct scsi_host_template driver_template = {
4394 .sg_tablesize = SG_ALL, 4344 .sg_tablesize = SG_ALL,
4395 .cmd_per_lun = 1, 4345 .cmd_per_lun = 1,
4396 .use_clustering = ENABLE_CLUSTERING, 4346 .use_clustering = ENABLE_CLUSTERING,
4347 .proc_name = "esp",
4348 .proc_info = esp_proc_info,
4349};
4350
4351#ifndef CONFIG_SUN4
4352static struct of_device_id esp_match[] = {
4353 {
4354 .name = "SUNW,esp",
4355 .data = &esp_template,
4356 },
4357 {
4358 .name = "SUNW,fas",
4359 .data = &esp_template,
4360 },
4361 {
4362 .name = "esp",
4363 .data = &esp_template,
4364 },
4365 {},
4366};
4367MODULE_DEVICE_TABLE(of, esp_match);
4368
4369static struct of_platform_driver esp_sbus_driver = {
4370 .name = "esp",
4371 .match_table = esp_match,
4372 .probe = esp_sbus_probe,
4373 .remove = __devexit_p(esp_sbus_remove),
4397}; 4374};
4375#endif
4376
4377static int __init esp_init(void)
4378{
4379#ifdef CONFIG_SUN4
4380 return esp_sun4_probe(&esp_template);
4381#else
4382 return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
4383#endif
4384}
4398 4385
4399#include "scsi_module.c" 4386static void __exit esp_exit(void)
4387{
4388#ifdef CONFIG_SUN4
4389 esp_sun4_remove();
4390#else
4391 of_unregister_driver(&esp_sbus_driver);
4392#endif
4393}
4400 4394
4401MODULE_DESCRIPTION("EnhancedScsiProcessor Sun SCSI driver"); 4395MODULE_DESCRIPTION("ESP Sun SCSI driver");
4402MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); 4396MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
4403MODULE_LICENSE("GPL"); 4397MODULE_LICENSE("GPL");
4404MODULE_VERSION(DRV_VERSION); 4398MODULE_VERSION(DRV_VERSION);
4405 4399
4400module_init(esp_init);
4401module_exit(esp_exit);