atp870u.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,735 行 · 第 1/4 页
C
2,735 行
if ((j & 0x08) != 0) { j = (j & 0x07) | 0x40; } /* * Check transfer direction */ if (workrequ->sc_data_direction == DMA_TO_DEVICE) { outb((unsigned char) (j | 0x20), tmport++); } else { outb(j, tmport++); } outb((unsigned char) (inb(tmport) | 0x80), tmport); outb(0x80, tmport); tmport = workportu + 0x1c; dev->id[target_id].dirctu = 0; if (l == 0) { if (inb(tmport) == 0) { tmport = workportu + 0x18; outb(0x08, tmport); } else { dev->last_cmd |= 0x40; } dev->in_snd = 0; return; } tmpcip = dev->pciport; prd = dev->id[target_id].prd_tableu; dev->id[target_id].prd_posu = prd; /* * Now write the request list. Either as scatter/gather or as * a linear chain. */ if (workrequ->use_sg) { sgpnt = (struct scatterlist *) workrequ->request_buffer; i = 0; for (j = 0; j < workrequ->use_sg; j++) { bttl = sg_dma_address(&sgpnt[j]); l = sg_dma_len(&sgpnt[j]); while (l > 0x10000) { (((u16 *) (prd))[i + 3]) = 0x0000; (((u16 *) (prd))[i + 2]) = 0x0000; (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); l -= 0x10000; bttl += 0x10000; i += 0x04; } (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); (((u16 *) (prd))[i + 3]) = 0; i += 0x04; } (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); } else { /* * For a linear request write a chain of blocks */ bttl = workrequ->SCp.dma_handle; l = workrequ->request_bufflen; i = 0; while (l > 0x10000) { (((u16 *) (prd))[i + 3]) = 0x0000; (((u16 *) (prd))[i + 2]) = 0x0000; (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); l -= 0x10000; bttl += 0x10000; i += 0x04; } (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000); (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); } tmpcip = tmpcip + 4; dev->id[target_id].prdaddru = dev->id[target_id].prd_phys; outl(dev->id[target_id].prd_phys, tmpcip); tmpcip = tmpcip - 2; outb(0x06, tmpcip); outb(0x00, tmpcip); tmpcip = tmpcip - 2; if (dev->deviceid != 0x8081) { tmport = workportu + 0x3a; if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { outb((inb(tmport) & 0xf3) | 0x08, tmport); } else { outb(inb(tmport) & 0xf3, tmport); } } else { tmport = workportu - 0x05; if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport); } else { outb((unsigned char) (inb(tmport) & 0x3f), tmport); } } tmport = workportu + 0x1c; if (workrequ->sc_data_direction == DMA_TO_DEVICE) { dev->id[target_id].dirctu = 0x20; if (inb(tmport) == 0) { tmport = workportu + 0x18; outb(0x08, tmport); outb(0x01, tmpcip); } else { dev->last_cmd |= 0x40; } dev->in_snd = 0; return; } if (inb(tmport) == 0) { tmport = workportu + 0x18; outb(0x08, tmport); outb(0x09, tmpcip); } else { dev->last_cmd |= 0x40; } dev->in_snd = 0;}static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val){ unsigned int tmport; unsigned short int i, k; unsigned char j; tmport = dev->ioport + 0x1c; outw(*val, tmport);FUN_D7: for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ k = inw(tmport); j = (unsigned char) (k >> 8); if ((k & 0x8000) != 0) { /* DB7 all release? */ goto FUN_D7; } } *val |= 0x4000; /* assert DB6 */ outw(*val, tmport); *val &= 0xdfff; /* assert DB5 */ outw(*val, tmport);FUN_D5: for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ goto FUN_D5; } } *val |= 0x8000; /* no DB4-0, assert DB7 */ *val &= 0xe0ff; outw(*val, tmport); *val &= 0xbfff; /* release DB6 */ outw(*val, tmport);FUN_D6: for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */ goto FUN_D6; } } return j;}static void tscam(struct Scsi_Host *host){ unsigned int tmport; unsigned char i, j, k; unsigned long n; unsigned short int m, assignid_map, val; unsigned char mbuf[33], quintet[2]; struct atp_unit *dev = (struct atp_unit *)&host->hostdata; static unsigned char g2q_tab[8] = { 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 };/* I can't believe we need this before we've even done anything. Remove it * and see if anyone bitches. for (i = 0; i < 0x10; i++) { udelay(0xffff); } */ tmport = dev->ioport + 1; outb(0x08, tmport++); outb(0x7f, tmport); tmport = dev->ioport + 0x11; outb(0x20, tmport); if ((dev->scam_on & 0x40) == 0) { return; } m = 1; m <<= dev->host_idu; j = 16; if (dev->chip_veru < 4) { m |= 0xff00; j = 8; } assignid_map = m; tmport = dev->ioport + 0x02; outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); for (i = 0; i < j; i++) { m = 1; m = m << i; if ((m & assignid_map) != 0) { continue; } tmport = dev->ioport + 0x0f; outb(0, tmport++); tmport += 0x02; outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); if (i > 7) { k = (i & 0x07) | 0x40; } else { k = i; } outb(k, tmport++); tmport = dev->ioport + 0x1b; if (dev->chip_veru == 4) { outb(0x01, tmport); } else { outb(0x00, tmport); }wait_rdyok: tmport = dev->ioport + 0x18; outb(0x09, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; k = inb(tmport); if (k != 0x16) { if ((k == 0x85) || (k == 0x42)) { continue; } tmport = dev->ioport + 0x10; outb(0x41, tmport); goto wait_rdyok; } assignid_map |= m; } tmport = dev->ioport + 0x02; outb(0x7f, tmport); tmport = dev->ioport + 0x1b; outb(0x02, tmport); outb(0, 0x80); val = 0x0080; /* bsy */ tmport = dev->ioport + 0x1c; outw(val, tmport); val |= 0x0040; /* sel */ outw(val, tmport); val |= 0x0004; /* msg */ outw(val, tmport); inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ val &= 0x007f; /* no bsy */ outw(val, tmport); mdelay(128); val &= 0x00fb; /* after 1ms no msg */ outw(val, tmport);wait_nomsg: if ((inb(tmport) & 0x04) != 0) { goto wait_nomsg; } outb(1, 0x80); udelay(100); for (n = 0; n < 0x30000; n++) { if ((inb(tmport) & 0x80) != 0) { /* bsy ? */ goto wait_io; } } goto TCM_SYNC;wait_io: for (n = 0; n < 0x30000; n++) { if ((inb(tmport) & 0x81) == 0x0081) { goto wait_io1; } } goto TCM_SYNC;wait_io1: inb(0x80); val |= 0x8003; /* io,cd,db7 */ outw(val, tmport); inb(0x80); val &= 0x00bf; /* no sel */ outw(val, tmport); outb(2, 0x80);TCM_SYNC: udelay(0x800); if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ outw(0, tmport--); outb(0, tmport); tmport = dev->ioport + 0x15; outb(0, tmport); tmport += 0x03; outb(0x09, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0); tmport -= 0x08; inb(tmport); return; } val &= 0x00ff; /* synchronization */ val |= 0x3f00; fun_scam(dev, &val); outb(3, 0x80); val &= 0x00ff; /* isolation */ val |= 0x2000; fun_scam(dev, &val); outb(4, 0x80); i = 8; j = 0;TCM_ID: if ((inw(tmport) & 0x2000) == 0) { goto TCM_ID; } outb(5, 0x80); val &= 0x00ff; /* get ID_STRING */ val |= 0x2000; k = fun_scam(dev, &val); if ((k & 0x03) == 0) { goto TCM_5; } mbuf[j] <<= 0x01; mbuf[j] &= 0xfe; if ((k & 0x02) != 0) { mbuf[j] |= 0x01; } i--; if (i > 0) { goto TCM_ID; } j++; i = 8; goto TCM_ID;TCM_5: /* isolation complete.. *//* mbuf[32]=0; printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ i = 15; j = mbuf[0]; if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ i = 7; } if ((j & 0x06) == 0) { /* IDvalid? */ goto G2Q5; } k = mbuf[1];small_id: m = 1; m <<= k; if ((m & assignid_map) == 0) { goto G2Q_QUIN; } if (k > 0) { k--; goto small_id; }G2Q5: /* srch from max acceptable ID# */ k = i; /* max acceptable ID# */G2Q_LP: m = 1; m <<= k; if ((m & assignid_map) == 0) { goto G2Q_QUIN; } if (k > 0) { k--; goto G2Q_LP; }G2Q_QUIN: /* k=binID#, */ assignid_map |= m; if (k < 8) { quintet[0] = 0x38; /* 1st dft ID<8 */ } else { quintet[0] = 0x31; /* 1st ID>=8 */ } k &= 0x07; quintet[1] = g2q_tab[k]; val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ m = quintet[0] << 8; val |= m; fun_scam(dev, &val); val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ m = quintet[1] << 8; val |= m; fun_scam(dev, &val); goto TCM_SYNC;}void is870(struct Scsi_Host *host, unsigned int wkport){ unsigned int tmport; unsigned char i, j, k, rmb, n; unsigned short int m; static unsigned char mbuf[512]; static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e }; static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 }; static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; struct atp_unit *dev = (struct atp_unit *)&host->hostdata; tmport = wkport + 0x3a; outb((unsigned char) (inb(tmport) | 0x10), tmport); for (i = 0; i < 16; i++) { if ((dev->chip_veru != 4) && (i > 7)) { break; } m = 1; m = m << i; if ((m & dev->active_idu) != 0) { continue; } if (i == dev->host_idu) { printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); continue; } tmport = wkport + 0x1b; if (dev->chip_veru == 4) { outb(0x01, tmport); } else { outb(0x00, tmport); } tmport = wkport + 1; outb(0x08, tmport++); outb(0x7f, tmport++); outb(satn[0], tmport++); outb(satn[1], tmport++); outb(satn[2], tmport++); outb(satn[3], tmport++); outb(satn[4], tmport++); outb(satn[5], tmport++); tmport += 0x06; outb(0, tmport); tmport += 0x02; outb(dev->id[i].devspu, tmport++); outb(0, tmport++); outb(satn[6], tmport++); outb(satn[7], tmport++); j = i; if ((j & 0x08) != 0) { j = (j & 0x07) | 0x40; } outb(j, tmport); tmport += 0x03; outb(satn[8], tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { continue; } while (inb(tmport) != 0x8e); dev->active_idu |= m; tmport = wkport + 0x10; outb(0x30, tmport); tmport = wkport + 0x04; outb(0x00, tmport);phase_cmd: tmport = wkport + 0x18; outb(0x08, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; j = inb(tmport); if (j != 0x16) { tmport = wkport + 0x10; outb(0x41, tmport); goto phase_cmd; }sel_ok: tmport = wkport + 3; outb(inqd[0], tmport++); outb(inqd[1], tmport++); outb(inqd[2], tmport++); outb(inqd[3], tmport++); outb(inqd[4], tmport++); outb(inqd[5], tmport); tmport += 0x07; outb(0, tmport); tmport += 0x02; outb(dev->id[i].devspu, tmport++); outb(0, tmport++); outb(inqd[6], tmport++); outb(inqd[7], tmport++); tmport += 0x03; outb(inqd[8], tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { continue; } while (inb(tmport) != 0x8e); tmport = wkport + 0x1b; if (dev->chip_veru == 4) { outb(0x00, tmport); } tmport = wkport + 0x18; outb(0x08, tmport); tmport += 0x07; j = 0;rd_inq_data: k = inb(tmport); if ((k & 0x01) != 0) { tmport -= 0x06; mbuf[j++] = inb(tmport); tmport += 0x06; goto rd_inq_data; } if ((k & 0x80) == 0) { goto rd_inq_data; } tmport -= 0x08; j = inb(tmport); if (j == 0x16) { goto inq_ok; } tmport = wkport + 0x10; outb(0x46, tmport); tmport += 0x02; outb(0, tmport++); outb(0, tmport++); outb(0, tmport++); tmport += 0x03; outb(0x08, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; if (inb(tmport) != 0x16) { goto sel_ok; }inq_ok: mbuf[36] = 0; printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); dev->id[i].devtypeu = mbuf[0]; rmb = mbuf[1]; n = mbuf[7]; if (dev->chip_veru != 4) { goto not_wide; } if ((mbuf[7] & 0x60) == 0) { goto not_wide; } if ((dev->global_map & 0x20) == 0) { goto not_wide; } tmport = wkport + 0x1b; outb(0x01, tmport); tmport = wkport + 3; outb(satn[0], tmport++); outb(satn[1], tmport++); outb(satn[2], tmport++); outb(satn[3], tmport++); outb(satn[4], tmport++); outb(satn[5], tmport++); tmport += 0x06; outb(0, tmport); tmport += 0x02; outb(dev->id[i].devspu, tmport++); outb(0, tmport++); outb(satn[6], tmport++); outb(satn[7], tmport++); tmport += 0x03; outb(satn[8], tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { continue; } while (inb(tmport) != 0x8e);try_wide: j = 0; tmport = wkport + 0x14; outb(0x05, tmport); tmport += 0x04; outb(0x20, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0) { if ((inb(tmport) & 0x01) != 0) { tmport -= 0x06; outb(wide[j++], tmport); tmport += 0x06; } } tmport -= 0x08; while ((inb(tmport) & 0x80) == 0x00); j = inb(tmport) & 0x0f; if (j == 0x0f) { goto widep_in; } if (j == 0x0a) { goto widep_cmd; } if (j == 0x0e) { goto try_wide; } continue;widep_out: tmport = wkport + 0x18; outb(0x20, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0) { if ((inb(tmport) & 0x01) != 0) { tmport -= 0x06; outb(0, tmport); tmport += 0x06; } } tmport -= 0x08; j = inb(tmport) & 0x0f; if (j == 0x0f) { goto widep_in; } if (j == 0x0a) { goto widep_cmd; } if (j == 0x0e) { goto widep_out; } continue;widep_in: tmport = wkport + 0x14; outb(0xff, tmport); tmport += 0x04; outb(0x20, tmport); tmport += 0x07; k = 0;widep_in1: j = inb(tmport); if ((j & 0x01) != 0) { tmport -= 0x06; mbuf[k++] = inb(tmport); tmport += 0x06; goto widep_in1; } if ((j & 0x80) == 0x00) { goto widep_in1; } tmport -= 0x08; j = inb(tmport) & 0x0f; if (j == 0x0f) { goto widep_in; } if (j == 0x0a) { goto widep_cmd; } if (j == 0x0e) { goto widep_out; } continue;widep_cmd: tmport = wkport + 0x10; outb(0x30, tmport); tmport = wkport + 0x14; outb(0x00, tmport); tmport += 0x04; outb(0x08, tmport); tmport += 0x07; while ((inb(tmport) & 0x80) == 0x00); tmport -= 0x08; j = inb(tmport);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?