Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc5 392 lines 10 kB view raw
1/* sun3x_esp.c: EnhancedScsiProcessor Sun3x SCSI driver code. 2 * 3 * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 4 * 5 * Based on David S. Miller's esp driver 6 */ 7 8#include <linux/kernel.h> 9#include <linux/types.h> 10#include <linux/string.h> 11#include <linux/slab.h> 12#include <linux/blkdev.h> 13#include <linux/proc_fs.h> 14#include <linux/stat.h> 15#include <linux/delay.h> 16#include <linux/interrupt.h> 17 18#include "scsi.h" 19#include <scsi/scsi_host.h> 20#include "NCR53C9x.h" 21 22#include <asm/sun3x.h> 23#include <asm/dvma.h> 24#include <asm/irq.h> 25 26static void dma_barrier(struct NCR_ESP *esp); 27static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); 28static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); 29static void dma_drain(struct NCR_ESP *esp); 30static void dma_invalidate(struct NCR_ESP *esp); 31static void dma_dump_state(struct NCR_ESP *esp); 32static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); 33static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); 34static void dma_ints_off(struct NCR_ESP *esp); 35static void dma_ints_on(struct NCR_ESP *esp); 36static int dma_irq_p(struct NCR_ESP *esp); 37static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr); 38static int dma_ports_p(struct NCR_ESP *esp); 39static void dma_reset(struct NCR_ESP *esp); 40static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); 41static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp); 42static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); 43static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp); 44static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); 45static void dma_advance_sg (Scsi_Cmnd *sp); 46 47/* Detecting ESP chips on the machine. This is the simple and easy 48 * version. 49 */ 50int sun3x_esp_detect(struct scsi_host_template *tpnt) 51{ 52 struct NCR_ESP *esp; 53 struct ConfigDev *esp_dev; 54 55 esp_dev = 0; 56 esp = esp_allocate(tpnt, (void *) esp_dev); 57 58 /* Do command transfer with DMA */ 59 esp->do_pio_cmds = 0; 60 61 /* Required functions */ 62 esp->dma_bytes_sent = &dma_bytes_sent; 63 esp->dma_can_transfer = &dma_can_transfer; 64 esp->dma_dump_state = &dma_dump_state; 65 esp->dma_init_read = &dma_init_read; 66 esp->dma_init_write = &dma_init_write; 67 esp->dma_ints_off = &dma_ints_off; 68 esp->dma_ints_on = &dma_ints_on; 69 esp->dma_irq_p = &dma_irq_p; 70 esp->dma_ports_p = &dma_ports_p; 71 esp->dma_setup = &dma_setup; 72 73 /* Optional functions */ 74 esp->dma_barrier = &dma_barrier; 75 esp->dma_invalidate = &dma_invalidate; 76 esp->dma_drain = &dma_drain; 77 esp->dma_irq_entry = 0; 78 esp->dma_irq_exit = 0; 79 esp->dma_led_on = 0; 80 esp->dma_led_off = 0; 81 esp->dma_poll = &dma_poll; 82 esp->dma_reset = &dma_reset; 83 84 /* virtual DMA functions */ 85 esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; 86 esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; 87 esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one; 88 esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl; 89 esp->dma_advance_sg = &dma_advance_sg; 90 91 /* SCSI chip speed */ 92 esp->cfreq = 20000000; 93 esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE); 94 esp->dregs = (void *)SUN3X_ESP_DMA; 95 96 esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE); 97 esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command); 98 99 esp->irq = 2; 100 if (request_irq(esp->irq, esp_intr, IRQF_DISABLED, 101 "SUN3X SCSI", esp->ehost)) { 102 esp_deallocate(esp); 103 return 0; 104 } 105 106 esp->scsi_id = 7; 107 esp->diff = 0; 108 109 esp_initialize(esp); 110 111 /* for reasons beyond my knowledge (and which should likely be fixed) 112 sync mode doesn't work on a 3/80 at 5mhz. but it does at 4. */ 113 esp->sync_defp = 0x3f; 114 115 printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, 116 esps_in_use); 117 esps_running = esps_in_use; 118 return esps_in_use; 119} 120 121static void dma_do_drain(struct NCR_ESP *esp) 122{ 123 struct sparc_dma_registers *dregs = 124 (struct sparc_dma_registers *) esp->dregs; 125 126 int count = 500000; 127 128 while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) 129 udelay(1); 130 131 if(!count) { 132 printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); 133 } 134 135 dregs->cond_reg |= DMA_FIFO_STDRAIN; 136 137 count = 500000; 138 139 while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) 140 udelay(1); 141 142 if(!count) { 143 printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); 144 } 145 146} 147 148static void dma_barrier(struct NCR_ESP *esp) 149{ 150 struct sparc_dma_registers *dregs = 151 (struct sparc_dma_registers *) esp->dregs; 152 int count = 500000; 153 154 while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) 155 udelay(1); 156 157 if(!count) { 158 printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); 159 } 160 161 dregs->cond_reg &= ~(DMA_ENABLE); 162} 163 164/* This uses various DMA csr fields and the fifo flags count value to 165 * determine how many bytes were successfully sent/received by the ESP. 166 */ 167static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) 168{ 169 struct sparc_dma_registers *dregs = 170 (struct sparc_dma_registers *) esp->dregs; 171 172 int rval = dregs->st_addr - esp->esp_command_dvma; 173 174 return rval - fifo_count; 175} 176 177static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) 178{ 179 return sp->SCp.this_residual; 180} 181 182static void dma_drain(struct NCR_ESP *esp) 183{ 184 struct sparc_dma_registers *dregs = 185 (struct sparc_dma_registers *) esp->dregs; 186 int count = 500000; 187 188 if(dregs->cond_reg & DMA_FIFO_ISDRAIN) { 189 dregs->cond_reg |= DMA_FIFO_STDRAIN; 190 while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) 191 udelay(1); 192 if(!count) { 193 printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); 194 } 195 196 } 197} 198 199static void dma_invalidate(struct NCR_ESP *esp) 200{ 201 struct sparc_dma_registers *dregs = 202 (struct sparc_dma_registers *) esp->dregs; 203 204 __u32 tmp; 205 int count = 500000; 206 207 while(((tmp = dregs->cond_reg) & DMA_PEND_READ) && (--count > 0)) 208 udelay(1); 209 210 if(!count) { 211 printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); 212 } 213 214 dregs->cond_reg = tmp | DMA_FIFO_INV; 215 dregs->cond_reg &= ~DMA_FIFO_INV; 216 217} 218 219static void dma_dump_state(struct NCR_ESP *esp) 220{ 221 struct sparc_dma_registers *dregs = 222 (struct sparc_dma_registers *) esp->dregs; 223 224 ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%08lx>\n", 225 esp->esp_id, dregs->cond_reg, dregs->st_addr)); 226} 227 228static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) 229{ 230 struct sparc_dma_registers *dregs = 231 (struct sparc_dma_registers *) esp->dregs; 232 233 dregs->st_addr = vaddress; 234 dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE); 235} 236 237static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) 238{ 239 struct sparc_dma_registers *dregs = 240 (struct sparc_dma_registers *) esp->dregs; 241 242 /* Set up the DMA counters */ 243 244 dregs->st_addr = vaddress; 245 dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE); 246} 247 248static void dma_ints_off(struct NCR_ESP *esp) 249{ 250 DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs); 251} 252 253static void dma_ints_on(struct NCR_ESP *esp) 254{ 255 DMA_INTSON((struct sparc_dma_registers *) esp->dregs); 256} 257 258static int dma_irq_p(struct NCR_ESP *esp) 259{ 260 return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs); 261} 262 263static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr) 264{ 265 int count = 50; 266 dma_do_drain(esp); 267 268 /* Wait till the first bits settle. */ 269 while((*(volatile unsigned char *)vaddr == 0xff) && (--count > 0)) 270 udelay(1); 271 272 if(!count) { 273// printk("%s:%d timeout expire (data %02x)\n", __FILE__, __LINE__, 274// esp_read(esp->eregs->esp_fdata)); 275 //mach_halt(); 276 vaddr[0] = esp_read(esp->eregs->esp_fdata); 277 vaddr[1] = esp_read(esp->eregs->esp_fdata); 278 } 279 280} 281 282static int dma_ports_p(struct NCR_ESP *esp) 283{ 284 return (((struct sparc_dma_registers *) esp->dregs)->cond_reg 285 & DMA_INT_ENAB); 286} 287 288/* Resetting various pieces of the ESP scsi driver chipset/buses. */ 289static void dma_reset(struct NCR_ESP *esp) 290{ 291 struct sparc_dma_registers *dregs = 292 (struct sparc_dma_registers *)esp->dregs; 293 294 /* Punt the DVMA into a known state. */ 295 dregs->cond_reg |= DMA_RST_SCSI; 296 dregs->cond_reg &= ~(DMA_RST_SCSI); 297 DMA_INTSON(dregs); 298} 299 300static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) 301{ 302 struct sparc_dma_registers *dregs = 303 (struct sparc_dma_registers *) esp->dregs; 304 unsigned long nreg = dregs->cond_reg; 305 306// printk("dma_setup %c addr %08x cnt %08x\n", 307// write ? 'W' : 'R', addr, count); 308 309 dma_do_drain(esp); 310 311 if(write) 312 nreg |= DMA_ST_WRITE; 313 else { 314 nreg &= ~(DMA_ST_WRITE); 315 } 316 317 nreg |= DMA_ENABLE; 318 dregs->cond_reg = nreg; 319 dregs->st_addr = addr; 320} 321 322static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) 323{ 324 sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer, 325 sp->SCp.this_residual); 326 sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in); 327} 328 329static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) 330{ 331 int sz = sp->SCp.buffers_residual; 332 struct scatterlist *sg = sp->SCp.buffer; 333 334 while (sz >= 0) { 335 sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) + 336 sg[sz].offset, sg[sz].length); 337 sz--; 338 } 339 sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); 340} 341 342static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) 343{ 344 dvma_unmap((char *)sp->SCp.have_data_in); 345} 346 347static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) 348{ 349 int sz = sp->use_sg - 1; 350 struct scatterlist *sg = (struct scatterlist *)sp->request_buffer; 351 352 while(sz >= 0) { 353 dvma_unmap((char *)sg[sz].dma_address); 354 sz--; 355 } 356} 357 358static void dma_advance_sg (Scsi_Cmnd *sp) 359{ 360 sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address); 361} 362 363static int sun3x_esp_release(struct Scsi_Host *instance) 364{ 365 /* this code does not support being compiled as a module */ 366 return 1; 367 368} 369 370static struct scsi_host_template driver_template = { 371 .proc_name = "sun3x_esp", 372 .proc_info = &esp_proc_info, 373 .name = "Sun ESP 100/100a/200", 374 .detect = sun3x_esp_detect, 375 .release = sun3x_esp_release, 376 .slave_alloc = esp_slave_alloc, 377 .slave_destroy = esp_slave_destroy, 378 .info = esp_info, 379 .queuecommand = esp_queue, 380 .eh_abort_handler = esp_abort, 381 .eh_bus_reset_handler = esp_reset, 382 .can_queue = 7, 383 .this_id = 7, 384 .sg_tablesize = SG_ALL, 385 .cmd_per_lun = 1, 386 .use_clustering = DISABLE_CLUSTERING, 387}; 388 389 390#include "scsi_module.c" 391 392MODULE_LICENSE("GPL");