Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Oak Generic NCR5380 driver
  4 *
  5 * Copyright 1995-2002, Russell King
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/ioport.h>
 10#include <linux/blkdev.h>
 11#include <linux/init.h>
 12
 13#include <asm/ecard.h>
 14#include <asm/io.h>
 15
 16#include <scsi/scsi_host.h>
 17
 
 
 
 18#define priv(host)			((struct NCR5380_hostdata *)(host)->hostdata)
 19
 20#define NCR5380_read(reg)           readb(hostdata->io + ((reg) << 2))
 21#define NCR5380_write(reg, value)   writeb(value, hostdata->io + ((reg) << 2))
 
 
 22
 23#define NCR5380_dma_xfer_len		NCR5380_dma_xfer_none
 24#define NCR5380_dma_recv_setup		oakscsi_pread
 25#define NCR5380_dma_send_setup		oakscsi_pwrite
 26#define NCR5380_dma_residual		NCR5380_dma_residual_none
 27
 28#define NCR5380_queue_command		oakscsi_queue_command
 29#define NCR5380_info			oakscsi_info
 30
 31#define NCR5380_implementation_fields	/* none */
 
 32
 33#include "../NCR5380.h"
 34
 35#undef START_DMA_INITIATOR_RECEIVE_REG
 36#define START_DMA_INITIATOR_RECEIVE_REG	(128 + 7)
 37
 38#define STAT	((128 + 16) << 2)
 39#define DATA	((128 + 8) << 2)
 40
 41static inline int oakscsi_pwrite(struct NCR5380_hostdata *hostdata,
 42                                 unsigned char *addr, int len)
 43{
 44  u8 __iomem *base = hostdata->io;
 45
 46printk("writing %p len %d\n",addr, len);
 
 47
 48  while(1)
 49  {
 50    int status;
 51    while (((status = readw(base + STAT)) & 0x100)==0);
 52  }
 53  return 0;
 54}
 55
 56static inline int oakscsi_pread(struct NCR5380_hostdata *hostdata,
 57                                unsigned char *addr, int len)
 58{
 59  u8 __iomem *base = hostdata->io;
 60
 61printk("reading %p len %d\n", addr, len);
 62  while(len > 0)
 63  {
 64    unsigned int status, timeout;
 65    unsigned long b;
 66    
 67    timeout = 0x01FFFFFF;
 68    
 69    while (((status = readw(base + STAT)) & 0x100)==0)
 70    {
 71      timeout--;
 72      if(status & 0x200 || !timeout)
 73      {
 74        printk("status = %08X\n", status);
 75        return -1;
 76      }
 77    }
 78
 79    if(len >= 128)
 80    {
 81      readsw(base + DATA, addr, 128);
 82      addr += 128;
 83      len -= 128;
 84    }
 85    else
 86    {
 87      b = (unsigned long) readw(base + DATA);
 88      *addr ++ = b;
 89      len -= 1;
 90      if(len)
 91        *addr ++ = b>>8;
 92      len -= 1;
 93    }
 94  }
 95  return 0;
 96}
 97
 98#undef STAT
 99#undef DATA
100
101#include "../NCR5380.c"
102
103static const struct scsi_host_template oakscsi_template = {
104	.module			= THIS_MODULE,
105	.name			= "Oak 16-bit SCSI",
106	.info			= oakscsi_info,
107	.queuecommand		= oakscsi_queue_command,
108	.eh_abort_handler	= NCR5380_abort,
109	.eh_host_reset_handler	= NCR5380_host_reset,
110	.can_queue		= 16,
111	.this_id		= 7,
112	.sg_tablesize		= SG_ALL,
113	.cmd_per_lun		= 2,
114	.dma_boundary		= PAGE_SIZE - 1,
115	.proc_name		= "oakscsi",
116	.cmd_size		= sizeof(struct NCR5380_cmd),
117	.max_sectors		= 128,
118};
119
120static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
121{
122	struct Scsi_Host *host;
123	int ret;
124
125	ret = ecard_request_resources(ec);
126	if (ret)
127		goto out;
128
129	host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata));
130	if (!host) {
131		ret = -ENOMEM;
132		goto release;
133	}
134
135	priv(host)->io = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
136	                         ecard_resource_len(ec, ECARD_RES_MEMC));
137	if (!priv(host)->io) {
138		ret = -ENOMEM;
139		goto unreg;
140	}
141
142	host->irq = NO_IRQ;
 
143
144	ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP);
145	if (ret)
146		goto out_unmap;
147
148	NCR5380_maybe_reset_bus(host);
149
150	ret = scsi_add_host(host, &ec->dev);
151	if (ret)
152		goto out_exit;
153
154	scsi_scan_host(host);
155	goto out;
156
157 out_exit:
158	NCR5380_exit(host);
159 out_unmap:
160	iounmap(priv(host)->io);
161 unreg:
162	scsi_host_put(host);
163 release:
164	ecard_release_resources(ec);
165 out:
166	return ret;
167}
168
169static void oakscsi_remove(struct expansion_card *ec)
170{
171	struct Scsi_Host *host = ecard_get_drvdata(ec);
172	void __iomem *base = priv(host)->io;
173
174	ecard_set_drvdata(ec, NULL);
175	scsi_remove_host(host);
176
177	NCR5380_exit(host);
 
178	scsi_host_put(host);
179	iounmap(base);
180	ecard_release_resources(ec);
181}
182
183static const struct ecard_id oakscsi_cids[] = {
184	{ MANU_OAK, PROD_OAK_SCSI },
185	{ 0xffff, 0xffff }
186};
187
188static struct ecard_driver oakscsi_driver = {
189	.probe		= oakscsi_probe,
190	.remove		= oakscsi_remove,
191	.id_table	= oakscsi_cids,
192	.drv = {
193		.name		= "oakscsi",
194	},
195};
196
197static int __init oakscsi_init(void)
198{
199	return ecard_register_driver(&oakscsi_driver);
200}
201
202static void __exit oakscsi_exit(void)
203{
204	ecard_remove_driver(&oakscsi_driver);
205}
206
207module_init(oakscsi_init);
208module_exit(oakscsi_exit);
209
210MODULE_AUTHOR("Russell King");
211MODULE_DESCRIPTION("Oak SCSI driver");
212MODULE_LICENSE("GPL");
213
v4.6
 
  1/*
  2 * Oak Generic NCR5380 driver
  3 *
  4 * Copyright 1995-2002, Russell King
  5 */
  6
  7#include <linux/module.h>
  8#include <linux/ioport.h>
  9#include <linux/blkdev.h>
 10#include <linux/init.h>
 11
 12#include <asm/ecard.h>
 13#include <asm/io.h>
 14
 15#include <scsi/scsi_host.h>
 16
 17/*#define PSEUDO_DMA*/
 18#define DONT_USE_INTR
 19
 20#define priv(host)			((struct NCR5380_hostdata *)(host)->hostdata)
 21
 22#define NCR5380_read(reg) \
 23	readb(priv(instance)->base + ((reg) << 2))
 24#define NCR5380_write(reg, value) \
 25	writeb(value, priv(instance)->base + ((reg) << 2))
 26
 27#define NCR5380_dma_xfer_len(instance, cmd, phase)	(cmd->transfersize)
 
 
 
 28
 29#define NCR5380_queue_command		oakscsi_queue_command
 30#define NCR5380_info			oakscsi_info
 31
 32#define NCR5380_implementation_fields	\
 33	void __iomem *base
 34
 35#include "../NCR5380.h"
 36
 37#undef START_DMA_INITIATOR_RECEIVE_REG
 38#define START_DMA_INITIATOR_RECEIVE_REG	(128 + 7)
 39
 40#define STAT	((128 + 16) << 2)
 41#define DATA	((128 + 8) << 2)
 42
 43static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
 44              int len)
 45{
 46  void __iomem *base = priv(instance)->base;
 47
 48printk("writing %p len %d\n",addr, len);
 49  if(!len) return -1;
 50
 51  while(1)
 52  {
 53    int status;
 54    while (((status = readw(base + STAT)) & 0x100)==0);
 55  }
 
 56}
 57
 58static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
 59              int len)
 60{
 61  void __iomem *base = priv(instance)->base;
 
 62printk("reading %p len %d\n", addr, len);
 63  while(len > 0)
 64  {
 65    unsigned int status, timeout;
 66    unsigned long b;
 67    
 68    timeout = 0x01FFFFFF;
 69    
 70    while (((status = readw(base + STAT)) & 0x100)==0)
 71    {
 72      timeout--;
 73      if(status & 0x200 || !timeout)
 74      {
 75        printk("status = %08X\n", status);
 76        return 1;
 77      }
 78    }
 79
 80    if(len >= 128)
 81    {
 82      readsw(base + DATA, addr, 128);
 83      addr += 128;
 84      len -= 128;
 85    }
 86    else
 87    {
 88      b = (unsigned long) readw(base + DATA);
 89      *addr ++ = b;
 90      len -= 1;
 91      if(len)
 92        *addr ++ = b>>8;
 93      len -= 1;
 94    }
 95  }
 96  return 0;
 97}
 98
 99#undef STAT
100#undef DATA
101
102#include "../NCR5380.c"
103
104static struct scsi_host_template oakscsi_template = {
105	.module			= THIS_MODULE,
106	.name			= "Oak 16-bit SCSI",
107	.info			= oakscsi_info,
108	.queuecommand		= oakscsi_queue_command,
109	.eh_abort_handler	= NCR5380_abort,
110	.eh_bus_reset_handler	= NCR5380_bus_reset,
111	.can_queue		= 16,
112	.this_id		= 7,
113	.sg_tablesize		= SG_ALL,
114	.cmd_per_lun		= 2,
115	.use_clustering		= DISABLE_CLUSTERING,
116	.proc_name		= "oakscsi",
117	.cmd_size		= NCR5380_CMD_SIZE,
118	.max_sectors		= 128,
119};
120
121static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
122{
123	struct Scsi_Host *host;
124	int ret = -ENOMEM;
125
126	ret = ecard_request_resources(ec);
127	if (ret)
128		goto out;
129
130	host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata));
131	if (!host) {
132		ret = -ENOMEM;
133		goto release;
134	}
135
136	priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
137				   ecard_resource_len(ec, ECARD_RES_MEMC));
138	if (!priv(host)->base) {
139		ret = -ENOMEM;
140		goto unreg;
141	}
142
143	host->irq = NO_IRQ;
144	host->n_io_port = 255;
145
146	ret = NCR5380_init(host, 0);
147	if (ret)
148		goto out_unmap;
149
150	NCR5380_maybe_reset_bus(host);
151
152	ret = scsi_add_host(host, &ec->dev);
153	if (ret)
154		goto out_exit;
155
156	scsi_scan_host(host);
157	goto out;
158
159 out_exit:
160	NCR5380_exit(host);
161 out_unmap:
162	iounmap(priv(host)->base);
163 unreg:
164	scsi_host_put(host);
165 release:
166	ecard_release_resources(ec);
167 out:
168	return ret;
169}
170
171static void oakscsi_remove(struct expansion_card *ec)
172{
173	struct Scsi_Host *host = ecard_get_drvdata(ec);
 
174
175	ecard_set_drvdata(ec, NULL);
176	scsi_remove_host(host);
177
178	NCR5380_exit(host);
179	iounmap(priv(host)->base);
180	scsi_host_put(host);
 
181	ecard_release_resources(ec);
182}
183
184static const struct ecard_id oakscsi_cids[] = {
185	{ MANU_OAK, PROD_OAK_SCSI },
186	{ 0xffff, 0xffff }
187};
188
189static struct ecard_driver oakscsi_driver = {
190	.probe		= oakscsi_probe,
191	.remove		= oakscsi_remove,
192	.id_table	= oakscsi_cids,
193	.drv = {
194		.name		= "oakscsi",
195	},
196};
197
198static int __init oakscsi_init(void)
199{
200	return ecard_register_driver(&oakscsi_driver);
201}
202
203static void __exit oakscsi_exit(void)
204{
205	ecard_remove_driver(&oakscsi_driver);
206}
207
208module_init(oakscsi_init);
209module_exit(oakscsi_exit);
210
211MODULE_AUTHOR("Russell King");
212MODULE_DESCRIPTION("Oak SCSI driver");
213MODULE_LICENSE("GPL");
214