diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
commit | 99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch) | |
tree | 3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/fc4 | |
parent | e73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff) |
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/fc4')
-rw-r--r-- | drivers/fc4/fc.c | 24 | ||||
-rw-r--r-- | drivers/fc4/fcp_impl.h | 2 | ||||
-rw-r--r-- | drivers/fc4/soc.c | 239 | ||||
-rw-r--r-- | drivers/fc4/soc.h | 70 | ||||
-rw-r--r-- | drivers/fc4/socal.c | 328 | ||||
-rw-r--r-- | drivers/fc4/socal.h | 38 |
6 files changed, 405 insertions, 296 deletions
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 8b45510a1..792db2fd8 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -54,29 +54,29 @@ #endif #ifdef __sparc__ -static inline void *fc_dma_alloc(long size, char *name, dma_handle *dma) +static inline void *fc_dma_alloc(long size, dma_handle *dma, fc_channel *fc) { - return (void *) sparc_dvma_malloc (size, name, dma); + return sbus_alloc_consistant(fc->dev, size, dma); } -static inline dma_handle fc_sync_dma_entry(void *buf, int len, fc_channel *fc) +static inline dma_handle fc_sync_dma_entry(void *buf, long len, fc_channel *fc) { - return mmu_get_scsi_one (buf, len, fc->dev->my_bus); + return sbus_map_single(fc->dev, buf, len); } static inline void fc_sync_dma_exit(dma_handle dmh, long size, fc_channel *fc) { - mmu_release_scsi_one (dmh, size, fc->dev->my_bus); + sbus_unmap_single(fc->dev, dmh, size); } static inline void fc_sync_dma_entry_sg(struct scatterlist *list, int count, fc_channel *fc) { - mmu_get_scsi_sgl((struct mmu_sglist *)list, count - 1, fc->dev->my_bus); + sbus_map_sg(fc->dev, list, count); } static inline void fc_sync_dma_exit_sg(struct scatterlist *list, int count, fc_channel *fc) { - mmu_release_scsi_sgl ((struct mmu_sglist *)list, count - 1, fc->dev->my_bus); + sbus_unmap_sg(fc->dev, list, count); } #else #error Port this @@ -352,7 +352,7 @@ void fcp_register(fc_channel *fc, u8 type, int unregister) if (!unregister) { fc->scsi_cmd_pool = (fcp_cmd *) fc_dma_alloc (slots * (sizeof (fcp_cmd) + fc->rsp_size), - "FCP SCSI cmd & rsp queues", &fc->dma_scsi_cmd); + &fc->dma_scsi_cmd, fc); fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots); fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd); fc->scsi_bitmap_end = (slots + 63) & ~63; @@ -555,7 +555,7 @@ int fcp_initialize(fc_channel *fcchain, int count) l->timer.function = fcp_login_timeout; l->timer.data = (unsigned long)l; atomic_set (&l->todo, count); - l->logi = kmalloc (count * 3 * sizeof(logi), GFP_DMA); + l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL); l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l->logi || !l->fcmds) { if (l->logi) kfree (l->logi); @@ -821,7 +821,7 @@ static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, i if (SCpnt->use_sg > 1) printk ("%s: SG for use_sg > 1 not handled yet\n", fc->name); fc_sync_dma_entry_sg (sg, SCpnt->use_sg, fc); fcmd->data = sg->dvma_address; - cmd->fcp_data_len = sg->length; + cmd->fcp_data_len = sg->dvma_length; } } memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -1103,7 +1103,7 @@ int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport) logi *l; int status; - l = (logi *)kmalloc(2 * sizeof(logi), GFP_DMA); + l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL); if (!l) return -ENOMEM; memset(l, 0, 2 * sizeof(logi)); l->code = LS_PLOGI; @@ -1138,7 +1138,7 @@ int fc_do_prli(fc_channel *fc, unsigned char alpa) prli *p; int status; - p = (prli *)kmalloc(2 * sizeof(prli), GFP_DMA); + p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL); if (!p) return -ENOMEM; memset(p, 0, 2 * sizeof(prli)); p->code = LS_PRLI; diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h index d52b89c73..c7e0987be 100644 --- a/drivers/fc4/fcp_impl.h +++ b/drivers/fc4/fcp_impl.h @@ -84,7 +84,7 @@ typedef struct _fc_channel { common_svc_parm *common_svc; svc_parm *class_svcs; #ifdef __sparc__ - struct linux_sbus_device *dev; + struct sbus_dev *dev; #endif struct module *module; /* FCP SCSI stuff */ diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index caa11c33e..c44c3fc8c 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -66,16 +66,18 @@ struct soc *socs = NULL; static inline void soc_disable(struct soc *s) { - s->regs->imask = 0; s->regs->cmd = SOC_CMD_SOFT_RESET; + sbus_writel(0, s->regs + IMASK); + sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD); } static inline void soc_enable(struct soc *s) { SOD(("enable %08x\n", s->cfg)) - s->regs->sae = 0; s->regs->cfg = s->cfg; - s->regs->cmd = SOC_CMD_RSP_QALL; + sbus_writel(0, s->regs + SAE); + sbus_writel(s->cfg, s->regs + CFG); + sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD); SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK))); } static void soc_reset(fc_channel *fc) @@ -114,23 +116,29 @@ static void inline soc_solicited (struct soc *s) sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q]; if (sw_cq->pool == NULL) - sw_cq->pool = - (soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16))); + sw_cq->pool = (soc_req *) + (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address)); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - SOD (("soc_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) + SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last)) for (;;) { hwrsp = (soc_rsp *)sw_cq->pool + sw_cq->out; token = xram_get_32low ((xram_p)&hwrsp->shdr.token); status = xram_get_32low ((xram_p)&hwrsp->status); fc = (fc_channel *)(&s->port[(token >> 11) & 1]); - if (status == SOC_OK) - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL); - else { + if (status == SOC_OK) { + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + FC_STATUS_OK, NULL); + } else { xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr)); - /* We have intentionally defined FC_STATUS_* constants to match SOC_* constants, otherwise - we'd have to translate status */ - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr); + /* We have intentionally defined FC_STATUS_* constants + * to match SOC_* constants, otherwise we'd have to + * translate status. + */ + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + status, &fchdr); } if (++sw_cq->out > sw_cq->last) { @@ -142,9 +150,13 @@ static void inline soc_solicited (struct soc *s) sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)); + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) break; @@ -156,15 +168,18 @@ static void inline soc_solicited (struct soc *s) static void inline soc_request (struct soc *s, u32 cmd) { SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL)); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); - SOD(("Queues available %08x OUT %X %X\n", cmd, xram_get_8((xram_p)&s->req[0].hw_cq->out), xram_get_8((xram_p)&s->req[0].hw_cq->out))) + SOD(("Queues available %08x OUT %X %X\n", cmd, + xram_get_8((xram_p)&s->req[0].hw_cq->out), + xram_get_8((xram_p)&s->req[0].hw_cq->out))) if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else + } else { fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); + } if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) s->curr_port ^= 1; } @@ -180,8 +195,8 @@ static void inline soc_unsolicited (struct soc *s) sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q]; if (sw_cq->pool == NULL) - sw_cq->pool = - (soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16))); + sw_cq->pool = (soc_req *) + (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address))); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) @@ -190,30 +205,37 @@ static void inline soc_unsolicited (struct soc *s) hwrsp = (soc_rsp *)sw_cq->pool + sw_cq->out; hwrspc = NULL; - flags = hwrsp->shdr.flags; + flags = xram_get_16 ((xram_p)&hwrsp->shdr.flags); count = xram_get_8 ((xram_p)&hwrsp->count); fc = (fc_channel *)&s->port[flags & SOC_PORT_B]; - SOD(("FC %08lx fcp_state_change %08lx\n", (long)fc, (long)fc->fcp_state_change)) + SOD(("FC %08lx fcp_state_change %08lx\n", + (long)fc, (long)fc->fcp_state_change)) if (count != 1) { /* Ugh, continuation entries */ u8 in; if (count != 2) { - printk("%s: Too many continuations entries %d\n", fc->name, count); + printk("%s: Too many continuations entries %d\n", + fc->name, count); goto update_out; } in = sw_cq->in; if (in < sw_cq->out) in += sw_cq->last + 1; if (in < sw_cq->out + 2) { - /* Ask the hardware about it if they haven't arrived yet */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)); + /* Ask the hardware if they haven't arrived yet. */ + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) /* Nothing came, let us wait */ return; } @@ -236,7 +258,8 @@ static void inline soc_unsolicited (struct soc *s) fcp_state_change(fc, FC_STATE_OFFLINE); break; default: - printk ("%s: Unknown STATUS no %d\n", fc->name, status); + printk ("%s: Unknown STATUS no %d\n", + fc->name, status); break; } break; @@ -248,29 +271,40 @@ static void inline soc_unsolicited (struct soc *s) if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt); - if (len < 4 || !hwrspc) - printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl); - else { - if (len > 60) len = 60; - xram_copy_from (buf, (xram_p)hwrspc, (len + 3) & ~3); + if (len < 4 || !hwrspc) { + printk ("%s: Invalid R_CTL %02x " + "continuation entries\n", + fc->name, r_ctl); + } else { + if (len > 60) + len = 60; + xram_copy_from (buf, (xram_p)hwrspc, + (len + 3) & ~3); if (*(u32 *)buf == LS_DISPLAY) { int i; for (i = 4; i < len; i++) - if (buf[i] == '\n') buf[i] = ' '; + if (buf[i] == '\n') + buf[i] = ' '; buf[len] = 0; - printk ("%s message: %s\n", fc->name, buf + 4); - } else - printk ("%s: Unknown LS_CMD %02x\n", fc->name, buf[0]); + printk ("%s message: %s\n", + fc->name, buf + 4); + } else { + printk ("%s: Unknown LS_CMD " + "%02x\n", fc->name, + buf[0]); + } } - } else - printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl); + } else { + printk ("%s: Unsolicited R_CTL %02x " + "not handled\n", fc->name, r_ctl); + } } break; default: printk ("%s: Unexpected flags %08x\n", fc->name, flags); break; - } + }; update_out: if (++sw_cq->out > sw_cq->last) { sw_cq->seqno++; @@ -288,9 +322,13 @@ update_out: sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)); + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); } } @@ -304,8 +342,8 @@ static void soc_intr(int irq, void *dev_id, struct pt_regs *regs) register struct soc *s = (struct soc *)dev_id; spin_lock_irqsave(&io_request_lock, flags); - cmd = s->regs->cmd; - for (; (cmd = SOC_INTR (s, cmd)); cmd = s->regs->cmd) { + cmd = sbus_readl(s->regs + CMD); + for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s); if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s); if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd); @@ -338,11 +376,11 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) sw_cq = s->req + qno; cq_next_in = (sw_cq->in + 1) & sw_cq->last; - if (cq_next_in == sw_cq->out - && cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) { + if (cq_next_in == sw_cq->out && + cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) { SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last)) SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno)); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); /* If queue is full, just say NO */ return -EBUSY; } @@ -363,7 +401,8 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) request->shdr.bytecnt = i; request->data[2].base = fcmd->data; request->data[2].count = i; - request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? + request->type = + (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ; } else { request->shdr.segcnt = 2; @@ -374,7 +413,8 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) } FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); + FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, + F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); fch->param = 0; @@ -388,7 +428,8 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) request->type = SOC_CQTYPE_OFFLINE; FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); + FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, + F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); request->shdr.flags = port->flags; @@ -436,7 +477,9 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) request->data[1].base = fcmd->rsp; request->data[0].count = fcmd->cmdlen; request->data[1].count = fcmd->rsplen; - request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE; + request->type = + (fcmd->class == FC_CLASS_IO_READ) ? + SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE; if (fcmd->data) { request->data[2].base = fcmd->data; request->data[2].count = fcmd->datalen; @@ -447,9 +490,9 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) request->shdr.segcnt = 2; } break; - } + }; break; - } + }; request->count = 1; request->flags = 0; @@ -462,11 +505,14 @@ static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) sw_cq->seqno++; } - SOD(("Putting %08x into cmd\n", SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno))) + SOD(("Putting %08x into cmd\n", + SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno))) - s->regs->cmd = SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno); - /* Read so that command is completed */ - s->regs->cmd; + sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno), + s->regs + CMD); + + /* Read so that command is completed. */ + sbus_readl(s->regs + CMD); return 0; } @@ -475,19 +521,19 @@ static inline void soc_download_fw(struct soc *s) { #ifdef HAVE_SOC_UCODE xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode)); - xram_bzero (s->xram + (sizeof(soc_ucode)/sizeof(u16)), 32768 - sizeof(soc_ucode)); + xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode)); #endif } /* Check for what the best SBUS burst we can use happens * to be on this machine. */ -static inline void soc_init_bursts(struct soc *s, struct linux_sbus_device *sdev) +static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev) { int bsizes, bsizes_more; bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff); + bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); bsizes &= bsizes_more; if ((bsizes & 0x7f) == 0x7f) s->cfg = SOC_CFG_BURST_64; @@ -499,22 +545,24 @@ static inline void soc_init_bursts(struct soc *s, struct linux_sbus_device *sdev s->cfg = SOC_CFG_BURST_4; } -static inline void soc_init(struct linux_sbus_device *sdev, int no) +static inline void soc_init(struct sbus_dev *sdev, int no) { unsigned char tmp[60]; int propl; struct soc *s; - static unsigned version_printed = 0; + static int version_printed = 0; soc_hw_cq cq[8]; int size, i; int irq; s = kmalloc (sizeof (struct soc), GFP_KERNEL); - if (!s) return; + if (s == NULL) + return; memset (s, 0, sizeof(struct soc)); s->soc_no = no; - SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", (long)socs, (long)soc_intr, (long)soc_hw_enque)) + SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", + (long)socs, (long)soc_intr, (long)soc_hw_enque)) if (version_printed++ == 0) printk (version); #ifdef MODULE @@ -558,9 +606,9 @@ static inline void soc_init(struct linux_sbus_device *sdev, int no) memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) s->port[0].fc.sid = 1; s->port[1].fc.sid = 17; @@ -570,26 +618,18 @@ static inline void soc_init(struct linux_sbus_device *sdev, int no) s->port[0].fc.reset = soc_reset; s->port[1].fc.reset = soc_reset; - /* Setup the reg property for this device. */ - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev); - if (sdev->num_registers == 1) { /* Probably SunFire onboard SOC */ - s->xram = (xram_p) - sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, - sdev->reg_addrs [0].reg_size, "soc_xram", - sdev->reg_addrs [0].which_io, 0); - s->regs = (struct soc_regs *)((char *)s->xram + 0x10000); + s->xram = sbus_ioremap(&sdev->resource[0], 0, + 0x10000UL, "soc xram"); + s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL, + 0x10UL, "soc regs"); } else { /* Probably SOC sbus card */ - s->xram = (xram_p) - sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, - sdev->reg_addrs [1].reg_size, "soc_xram", - sdev->reg_addrs [1].which_io, 0); - s->regs = (struct soc_regs *) - sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, - sdev->reg_addrs [2].reg_size, "soc_regs", - sdev->reg_addrs [2].which_io, 0); + s->xram = sbus_ioremap(&sdev->resource[1], 0, + sdev->reg_addrs[1].reg_size, "soc xram"); + s->regs = sbus_ioremap(&sdev->resource[2], 0, + sdev->reg_addrs[2].reg_size, "soc regs"); } soc_init_bursts(s, sdev); @@ -628,13 +668,15 @@ static inline void soc_init(struct linux_sbus_device *sdev, int no) memset (cq, 0, sizeof(cq)); size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req); - s->req[0].pool = (soc_req *) sparc_dvma_malloc (size, "SOC request queues", &cq[0].address); + s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma); + s->req[0].pool = s->req_cpu; + cq[0].address = s->req_dvma; s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE; s->req[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET); - s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq) / sizeof(u16)); + s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq)); s->rsp[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq) / sizeof(u16)); + s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq)); cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req)); cq[4].address = 1; @@ -677,13 +719,13 @@ int __init soc_probe(void) int init_module(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; struct soc *s; int cards = 0; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { if(!strcmp(sdev->prom_name, "SUNW,soc")) { soc_init(sdev, cards); cards++; @@ -706,7 +748,7 @@ void cleanup_module(void) { struct soc *s; int irq; - struct linux_sbus_device *sdev; + struct sbus_dev *sdev; for_each_soc(s) { irq = s->port[0].fc.irq; @@ -716,13 +758,16 @@ void cleanup_module(void) fcp_release(&(s->port[0].fc), 2); sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) - sparc_free_io ((char *)s->xram, sdev->reg_addrs [0].reg_size); - else { - sparc_free_io ((char *)s->xram, sdev->reg_addrs [1].reg_size); - sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size); + if (sdev->num_registers == 1) { + sbus_iounmap(s->xram, 0x10000UL); + sbus_iounmap(s->regs, 0x10UL); + } else { + sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); + sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); } - /* FIXME: sparc_dvma_free() ??? */ + sbus_free_consistant(sdev, + (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req), + s->req_cpu, s->req_dvma); } } #endif diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h index b02105bde..740e1a395 100644 --- a/drivers/fc4/soc.h +++ b/drivers/fc4/soc.h @@ -10,14 +10,11 @@ #include "fcp.h" #include "fcp_impl.h" -/* Hardware structures and constants first {{{ */ - -struct soc_regs { - volatile u32 cfg; /* Config Register */ - volatile u32 sae; /* Slave Access Error Register */ - volatile u32 cmd; /* Command & Status Register */ - volatile u32 imask; /* Interrupt Mask Register */ -}; +/* Hardware register offsets and constants first {{{ */ +#define CFG 0x00UL /* Config Register */ +#define SAE 0x04UL /* Slave Access Error Register */ +#define CMD 0x08UL /* Command and Status Register */ +#define IMASK 0x0cUL /* Interrupt Mask Register */ /* Config Register */ #define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000 @@ -74,7 +71,9 @@ struct soc_regs { & s->imask) #define SOC_SETIMASK(s, i) \ - (s)->imask = (i); (s)->regs->imask = (i) +do { (s)->imask = (i); \ + sbus_writel((i), (s)->regs + IMASK); \ +} while(0) /* XRAM * @@ -82,56 +81,66 @@ struct soc_regs { * That's why here are the following inline functions... */ -typedef u16 *xram_p; +typedef unsigned long xram_p; /* Get 32bit number from XRAM */ static inline u32 xram_get_32 (xram_p x) { - return (((u32)*x) << 16) | (x[1]); + return ((sbus_readw(x + 0x00UL) << 16) | + (sbus_readw(x + 0x02UL))); } /* Like the above, but when we don't care about the high 16 bits */ static inline u32 xram_get_32low (xram_p x) { - return (u32)x[1]; + return (u32) sbus_readw(x + 0x02UL); +} + +static inline u16 xram_get_16 (xram_p x) +{ + return sbus_readw(x); } static inline u8 xram_get_8 (xram_p x) { - if (((long)x) & 1) { - x = (xram_p)((long)x - 1); - return (u8)*x; - } else - return (u8)(*x >> 8); + if (x & (xram_p)0x1) { + x = x - 1; + return (u8) sbus_readw(x); + } else { + return (u8) (sbus_readw(x) >> 8); + } } static inline void xram_copy_from (void *p, xram_p x, int len) { - for (len >>= 2; len > 0; len--, x += 2) { - *((u32 *)p)++ = (((u32)(*x)) << 16) | (x[1]); + for (len >>= 2; len > 0; len--, x += sizeof(u32)) { + u32 val; + + val = ((sbus_readw(x + 0x00UL) << 16) | + (sbus_readw(x + 0x02UL))); + *((u32 *)p)++ = val; } } static inline void xram_copy_to (xram_p x, void *p, int len) { - register u32 tmp; - for (len >>= 2; len > 0; len--, x += 2) { - tmp = *((u32 *)p)++; - *x = tmp >> 16; - x[1] = tmp; + for (len >>= 2; len > 0; len--, x += sizeof(u32)) { + u32 tmp = *((u32 *)p)++; + sbus_writew(tmp >> 16, x + 0x00UL); + sbus_writew(tmp, x + 0x02UL); } } static inline void xram_bzero (xram_p x, int len) { - for (len >>= 1; len > 0; len--) *x++ = 0; + for (len >>= 1; len > 0; len--, x += sizeof(u16)) + sbus_writew(0, x); } /* Circular Queue */ -/* These two are in sizeof(u16) units */ -#define SOC_CQ_REQ_OFFSET 0x100 -#define SOC_CQ_RSP_OFFSET 0x110 +#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16)) +#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16)) typedef struct { u32 address; @@ -260,7 +269,7 @@ struct soc { soc_cq req[2]; /* Request CQs */ soc_cq rsp[2]; /* Response CQs */ int soc_no; - struct soc_regs *regs; + unsigned long regs; xram_p xram; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ @@ -268,6 +277,9 @@ struct soc { char serv_params[80]; struct soc *next; int curr_port; /* Which port will have priority to fcp_queue_empty */ + + soc_req *req_cpu; + u32 req_dvma; }; /* }}} */ diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index 6bcfbeacd..c63aaa6b8 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -61,23 +61,33 @@ static char *version = #define for_each_socal(s) for (s = socals; s; s = s->next) struct socal *socals = NULL; -/* I don't think our VIS mem* routines will behave well - in IO... */ -static void socal_memcpy(void *d, void *s, int size) +static void socal_copy_from_xram(void *d, unsigned long xram, long size) { - u32 *dp = (u32 *)d, *sp = (u32 *)s; + u32 *dp = (u32 *) d; while (size) { - *dp++ = *sp++; + *dp++ = sbus_readl(xram); + xram += sizeof(u32); + size -= sizeof(u32); + } +} + +static void socal_copy_to_xram(unsigned long xram, void *s, long size) +{ + u32 *sp = (u32 *) s; + while (size) { + u32 val = *sp++; + sbus_writel(val, xram); + xram += sizeof(u32); size -= sizeof(u32); } } #ifdef HAVE_SOCAL_UCODE -static void socal_bzero(void *d, int size) +static void socal_bzero(unsigned long xram, int size) { - u32 *dp = (u32 *)d; while (size) { - *dp++ = 0; + sbus_writel(0, xram); + xram += sizeof(u32); size -= sizeof(u32); } } @@ -85,16 +95,18 @@ static void socal_bzero(void *d, int size) static inline void socal_disable(struct socal *s) { - s->regs->imask = 0; s->regs->cmd = SOCAL_CMD_SOFT_RESET; + sbus_writel(0, s->regs + IMASK); + sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD); } static inline void socal_enable(struct socal *s) { SOD(("enable %08x\n", s->cfg)) - s->regs->sae = 0; s->regs->cfg = s->cfg; - s->regs->cmd = SOCAL_CMD_RSP_QALL; + sbus_writel(0, s->regs + SAE); + sbus_writel(s->cfg, s->regs + CFG); + sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD); SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); } static void socal_reset(fc_channel *fc) @@ -121,9 +133,8 @@ static void socal_reset(fc_channel *fc) socal_enable(s); } -static void inline socal_solicited (struct socal *s, int qno) +static void inline socal_solicited(struct socal *s, unsigned long qno) { - fc_hdr fchdr; socal_rsp *hwrsp; socal_cq *sw_cq; int token; @@ -132,14 +143,10 @@ static void inline socal_solicited (struct socal *s, int qno) sw_cq = &s->rsp[qno]; - if (sw_cq->pool == NULL) { - SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram)) - sw_cq->pool = - (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe)); - } /* Finally an improvement against old SOC :) */ - sw_cq->in = s->regs->respr[qno]; - SOD (("socal_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) + sw_cq->in = sbus_readb(s->regs + RESP + qno); + SOD (("socal_solicited, %d packets arrived\n", + (sw_cq->in - sw_cq->out) & sw_cq->last)) for (;;) { hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out)) @@ -147,16 +154,28 @@ static void inline socal_solicited (struct socal *s, int qno) #if defined(SOCALDEBUG) && 0 { u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u = (u32 *)s->xram; while (u < ((u32 *)s->regs)) { - if (u[0] == 0x00003000 || u[0] == 0x00003801) { - SOD(("Found at %04lx\n", (unsigned long)u - (unsigned long)s->xram)) - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + if (sbus_readl(&u[0]) == 0x00003000 || + sbus_readl(&u[0]) == 0x00003801) { + SOD(("Found at %04lx\n", + (unsigned long)u - (unsigned long)s->xram)) + SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + sbus_readl(&u[0]), sbus_readl(&u[1]), + sbus_readl(&u[2]), sbus_readl(&u[3]), + sbus_readl(&u[4]), sbus_readl(&u[5]), + sbus_readl(&u[6]), sbus_readl(&u[7]))) u += 8; - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + sbus_readl(&u[0]), sbus_readl(&u[1]), + sbus_readl(&u[2]), sbus_readl(&u[3]), + sbus_readl(&u[4]), sbus_readl(&u[5]), + sbus_readl(&u[6]), sbus_readl(&u[7]))) u -= 8; } u++; @@ -169,13 +188,17 @@ static void inline socal_solicited (struct socal *s, int qno) fc = (fc_channel *)(&s->port[(token >> 11) & 1]); SOD(("Solicited token %08x status %08x\n", token, status)) - if (status == SOCAL_OK) - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL); - else { - socal_memcpy(&fchdr, &hwrsp->fchdr, sizeof(fchdr)); - /* We have intentionally defined FC_STATUS_* constants to match SOCAL_* constants, otherwise - we'd have to translate status */ - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr); + if (status == SOCAL_OK) { + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + FC_STATUS_OK, NULL); + } else { + /* We have intentionally defined FC_STATUS_* constants + * to match SOCAL_* constants, otherwise we'd have to + * translate status. + */ + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), status, &hwrsp->fchdr); } if (++sw_cq->out > sw_cq->last) { @@ -184,13 +207,17 @@ static void inline socal_solicited (struct socal *s, int qno) } if (sw_cq->out == sw_cq->in) { - sw_cq->in = s->regs->respr[qno]; + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) break; } @@ -201,20 +228,21 @@ static void inline socal_solicited (struct socal *s, int qno) static void inline socal_request (struct socal *s, u32 cmd) { SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL)); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0])) if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else + } else { fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); + } if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) s->curr_port ^= 1; } -static void inline socal_unsolicited (struct socal *s, int qno) +static void inline socal_unsolicited (struct socal *s, unsigned long qno) { socal_rsp *hwrsp, *hwrspc; socal_cq *sw_cq; @@ -224,14 +252,10 @@ static void inline socal_unsolicited (struct socal *s, int qno) fc_channel *fc; sw_cq = &s->rsp[qno]; - if (sw_cq->pool == NULL) { - SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram)) - sw_cq->pool = - (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe)); - } - sw_cq->in = s->regs->respr[qno]; - SOD (("socal_unsolicited, %d packets arrived, in %d\n", (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in)) + sw_cq->in = sbus_readb(s->regs + RESP + qno); + SOD (("socal_unsolicited, %d packets arrived, in %d\n", + (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in)) while (sw_cq->in != sw_cq->out) { /* ...real work per entry here... */ hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; @@ -240,9 +264,11 @@ static void inline socal_unsolicited (struct socal *s, int qno) #if defined(SOCALDEBUG) && 0 { u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) } #endif @@ -257,20 +283,27 @@ static void inline socal_unsolicited (struct socal *s, int qno) u8 in; if (count != 2) { - printk("%s: Too many continuations entries %d\n", fc->name, count); + printk("%s: Too many continuations entries %d\n", + fc->name, count); goto update_out; } in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) { - /* Ask the hardware about it if they haven't arrived yet */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + /* Ask the hardware if they haven't arrived yet. */ + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) /* Nothing came, let us wait */ return; } @@ -297,42 +330,51 @@ static void inline socal_unsolicited (struct socal *s, int qno) fcp_state_change(fc, FC_STATE_OFFLINE); break; default: - printk ("%s: Unknown STATUS no %d\n", fc->name, status); + printk ("%s: Unknown STATUS no %d\n", + fc->name, status); break; - } + }; + break; case (SOCAL_UNSOLICITED|SOCAL_FC_HDR): { int r_ctl = *((u8 *)&hwrsp->fchdr); unsigned len; - char buf[64]; if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { len = hwrsp->shdr.bytecnt; - if (len < 4 || !hwrspc) - printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl); - else { - if (len > 60) len = 60; - socal_memcpy (buf, hwrspc, (len + 3) & ~3); - if (*(u32 *)buf == LS_DISPLAY) { + if (len < 4 || !hwrspc) { + printk ("%s: Invalid R_CTL %02x " + "continuation entries\n", + fc->name, r_ctl); + } else { + if (len > 60) + len = 60; + if (*(u32 *)hwrspc == LS_DISPLAY) { int i; for (i = 4; i < len; i++) - if (buf[i] == '\n') buf[i] = ' '; - buf[len] = 0; - printk ("%s message: %s\n", fc->name, buf + 4); + if (((u8 *)hwrspc)[i] == '\n') + ((u8 *)hwrspc)[i] = ' '; + ((u8 *)hwrspc)[len] = 0; + printk ("%s message: %s\n", + fc->name, ((u8 *)hwrspc) + 4); } else { - printk ("%s: Unknown LS_CMD %08x\n", fc->name, *(u32 *)buf); + printk ("%s: Unknown LS_CMD " + "%08x\n", fc->name, + *(u32 *)hwrspc); } } - } else - printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl); + } else { + printk ("%s: Unsolicited R_CTL %02x " + "not handled\n", fc->name, r_ctl); + } } break; default: printk ("%s: Unexpected flags %08x\n", fc->name, flags); break; - } + }; update_out: if (++sw_cq->out > sw_cq->last) { sw_cq->seqno++; @@ -347,13 +389,17 @@ update_out: } if (sw_cq->out == sw_cq->in) { - sw_cq->in = s->regs->respr[qno]; + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); } } } @@ -366,16 +412,21 @@ static void socal_intr(int irq, void *dev_id, struct pt_regs *regs) register struct socal *s = (struct socal *)dev_id; spin_lock_irqsave(&io_request_lock, flags); - cmd = s->regs->cmd; - for (; (cmd = SOCAL_INTR (s, cmd)); cmd = s->regs->cmd) { + cmd = sbus_readl(s->regs + CMD); + for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { #ifdef SOCALDEBUG static int cnt = 0; - if (cnt++ < 50) printk("soc_intr %08x\n", cmd); + if (cnt++ < 50) + printk("soc_intr %08x\n", cmd); #endif - if (cmd & SOCAL_CMD_RSP_Q2) socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q1) socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q0) socal_solicited (s, SOCAL_SOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_REQ_QALL) socal_request (s, cmd); + if (cmd & SOCAL_CMD_RSP_Q2) + socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q); + if (cmd & SOCAL_CMD_RSP_Q1) + socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q); + if (cmd & SOCAL_CMD_RSP_Q0) + socal_solicited (s, SOCAL_SOLICITED_RSP_Q); + if (cmd & SOCAL_CMD_REQ_QALL) + socal_request (s, cmd); } spin_unlock_irqrestore(&io_request_lock, flags); } @@ -386,7 +437,7 @@ static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) { socal_port *port = (socal_port *)fc; struct socal *s = port->s; - int qno; + unsigned long qno; socal_cq *sw_cq; int cq_next_in; socal_req *request; @@ -405,12 +456,15 @@ static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) sw_cq = s->req + qno; cq_next_in = (sw_cq->in + 1) & sw_cq->last; - if (cq_next_in == sw_cq->out - && cq_next_in == (sw_cq->out = s->regs->reqpr[qno])) { - SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last)) + if (cq_next_in == sw_cq->out && + cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) { + SOD(("%d IN %d OUT %d LAST %d\n", + qno, sw_cq->in, + sw_cq->out, sw_cq->last)) SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno)); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); - /* If queue is full, just say NO */ + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); + + /* If queue is full, just say NO. */ return -EBUSY; } @@ -540,9 +594,11 @@ static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno))) - s->regs->cmd = SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno); + sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno), + s->regs + CMD); + /* Read so that command is completed */ - s->regs->cmd; + sbus_readl(s->regs + CMD); return 0; } @@ -551,7 +607,7 @@ static inline void socal_download_fw(struct socal *s) { #ifdef HAVE_SOCAL_UCODE SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram)) - socal_memcpy (s->xram, socal_ucode, sizeof(socal_ucode)); + socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode)); SOD(("Clearing the rest of memory\n")) socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode)); SOD(("Done\n")) @@ -561,13 +617,13 @@ static inline void socal_download_fw(struct socal *s) /* Check for what the best SBUS burst we can use happens * to be on this machine. */ -static inline void socal_init_bursts(struct socal *s, struct linux_sbus_device *sdev) +static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev) { int bsizes, bsizes_more; u32 cfg; bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff); + bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); bsizes &= bsizes_more; #ifdef USE_64BIT_MODE #ifdef __sparc_v9__ @@ -598,7 +654,7 @@ static inline void socal_init_bursts(struct socal *s, struct linux_sbus_device * s->cfg = cfg; } -static inline void socal_init(struct linux_sbus_device *sdev, int no) +static inline void socal_init(struct sbus_dev *sdev, int no) { unsigned char tmp[60]; int propl; @@ -613,7 +669,8 @@ static inline void socal_init(struct linux_sbus_device *sdev, int no) memset (s, 0, sizeof(struct socal)); s->socal_no = no; - SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", (long)socals, (long)socal_intr, (long)socal_hw_enque)) + SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", + (long)socals, (long)socal_intr, (long)socal_hw_enque)) if (version_printed++ == 0) printk (version); #ifdef MODULE @@ -663,16 +720,17 @@ static inline void socal_init(struct linux_sbus_device *sdev, int no) break; default: break; - } + }; + node = prom_getsibling(node); } memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) + *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo, + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) s->port[0].fc.sid = 1; s->port[1].fc.sid = 17; @@ -682,29 +740,20 @@ static inline void socal_init(struct linux_sbus_device *sdev, int no) s->port[0].fc.reset = socal_reset; s->port[1].fc.reset = socal_reset; - /* Setup the reg property for this device. */ - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev); - if (sdev->num_registers == 1) { - s->eeprom = (u8 *) - sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, - sdev->reg_addrs [0].reg_size, "socal_xram", - sdev->reg_addrs [0].which_io, 0); - if (sdev->reg_addrs [0].reg_size > 0x20000) - s->xram = s->eeprom + 0x10000; + s->eeprom = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, "socal xram"); + if (sdev->reg_addrs[0].reg_size > 0x20000) + s->xram = s->eeprom + 0x10000UL; else s->xram = s->eeprom; - s->regs = (struct socal_regs *)(s->xram + 0x10000); + s->regs = (s->xram + 0x10000UL); } else { /* E.g. starfire presents 3 registers for SOCAL */ - s->xram = (u8 *) - sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, - sdev->reg_addrs [1].reg_size, "socal_xram", - sdev->reg_addrs [1].which_io, 0); - s->regs = (struct socal_regs *) - sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, - sdev->reg_addrs [2].reg_size, "socal_regs", - sdev->reg_addrs [2].which_io, 0); + s->xram = sbus_ioremap(&sdev->resource[1], 0, + sdev->reg_addrs[1].reg_size, "socal xram"); + s->regs = sbus_ioremap(&sdev->resource[2], 0, + sdev->reg_addrs[2].reg_size, "socal regs"); } socal_init_bursts(s, sdev); @@ -742,8 +791,12 @@ static inline void socal_init(struct linux_sbus_device *sdev, int no) /* Now setup xram circular queues */ memset (cq, 0, sizeof(cq)); - size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req); - s->req[0].pool = (socal_req *) sparc_dvma_malloc (size, "SOCAL request queues", &cq[0].address); + size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req); + s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma); + s->req[0].pool = s->req_cpu; + cq[0].address = s->req_dvma; s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE; s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE; s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE; @@ -780,12 +833,12 @@ static inline void socal_init(struct linux_sbus_device *sdev, int no) s->rsp[1].seqno = 1; s->rsp[2].seqno = 1; - socal_memcpy (s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq)); + socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq)); SOD(("Setting up params\n")) /* Make our sw copy of SOCAL service parameters */ - socal_memcpy (s->serv_params, s->xram + 0x280, sizeof (s->serv_params)); + socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params)); s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params; s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); @@ -803,20 +856,21 @@ int __init socal_probe(void) int init_module(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; struct socal *s; int cards = 0; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { if(!strcmp(sdev->prom_name, "SUNW,socal")) { socal_init(sdev, cards); cards++; } } } - if (!cards) return -EIO; + if (!cards) + return -EIO; for_each_socal(s) if (s->next) @@ -833,7 +887,7 @@ void cleanup_module(void) { struct socal *s; int irq; - struct linux_sbus_device *sdev; + struct sbus_dev *sdev; for_each_socal(s) { irq = s->port[0].fc.irq; @@ -843,13 +897,17 @@ void cleanup_module(void) fcp_release(&(s->port[0].fc), 2); sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) - sparc_free_io (s->eeprom, sdev->reg_addrs [0].reg_size); - else { - sparc_free_io (s->xram, sdev->reg_addrs [1].reg_size); - sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size); + if (sdev->num_registers == 1) { + sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size); + } else { + sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); + sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); } - /* FIXME: sparc_dvma_free() ??? */ + sbus_free_consistant(sdev, + (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req), + s->req_cpu, s->req_dvma); } } #endif diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h index 8bd62b3fc..8e8c7f451 100644 --- a/drivers/fc4/socal.h +++ b/drivers/fc4/socal.h @@ -10,24 +10,13 @@ #include "fcp.h" #include "fcp_impl.h" -/* Hardware structures and constants first {{{ */ - -union socal_rq_reg { - volatile u8 read[4]; - volatile u32 write; -}; -struct socal_regs { - volatile u32 cfg; /* Config Register */ - volatile u32 sae; /* Slave Access Error Register */ - volatile u32 cmd; /* Command & Status Register */ - volatile u32 imask; /* Interrupt Mask Register */ - union socal_rq_reg reqp; /* Request Queue Index Register */ - union socal_rq_reg resp; /* Response Queue Index Register */ -#define reqpr reqp.read -#define reqpw reqp.write -#define respr resp.read -#define respw resp.write -}; +/* Hardware register offsets and constants first {{{ */ +#define CFG 0x00UL +#define SAE 0x04UL +#define CMD 0x08UL +#define IMASK 0x0cUL +#define REQP 0x10UL +#define RESP 0x14UL /* Config Register */ #define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000 @@ -86,7 +75,9 @@ struct socal_regs { & s->imask) #define SOCAL_SETIMASK(s, i) \ - (s)->imask = (i); (s)->regs->imask = (i) +do { (s)->imask = (i); \ + sbus_writel((i), (s)->regs + IMASK); \ +} while (0) #define SOCAL_MAX_EXCHANGES 1024 @@ -303,15 +294,18 @@ struct socal { socal_cq req[4]; /* Request CQs */ socal_cq rsp[4]; /* Response CQs */ int socal_no; - struct socal_regs *regs; - u8 *xram; - u8 *eeprom; + unsigned long regs; + unsigned long xram; + unsigned long eeprom; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ u32 cfg; /* Our copy of regs->cfg */ char serv_params[80]; struct socal *next; int curr_port; /* Which port will have priority to fcp_queue_empty */ + + socal_req * req_cpu; + u32 req_dvma; }; /* }}} */ |