/*#define DEBUG 1 */
 /*#define UARTDELAY 1 */
 
-/* On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates
-   high pages. Keep the macro around because of the broken unmerged ia64 tree */
-
-#define ADDR32 (0)
-
 #include <linux/module.h>
 
 MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");
 
 static DEFINE_MUTEX(adpt_configuration_lock);
 
-static struct i2o_sys_tbl *sys_tbl = NULL;
-static int sys_tbl_ind = 0;
-static int sys_tbl_len = 0;
+static struct i2o_sys_tbl *sys_tbl;
+static dma_addr_t sys_tbl_pa;
+static int sys_tbl_ind;
+static int sys_tbl_len;
 
 static adpt_hba* hba_chain = NULL;
 static int hba_count = 0;
  *============================================================================
  */
 
+static inline u32 dma_high(dma_addr_t addr)
+{
+       return upper_32_bits(addr);
+}
+
+static inline u32 dma_low(dma_addr_t addr)
+{
+       return (u32)addr;
+}
+
 static u8 adpt_read_blink_led(adpt_hba* host)
 {
        if(host->FwDebugBLEDflag_P != 0) {
        u32 len;
        u32 reqlen;
        u8* buf;
+       dma_addr_t addr;
        u8  scb[16];
        s32 rcode;
 
        memset(msg, 0, sizeof(msg));
-       buf = kmalloc(80,GFP_KERNEL|ADDR32);
+       buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL);
        if(!buf){
                printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
                return;
        /* Now fill in the SGList and command */
        *lenptr = len;
        *mptr++ = 0xD0000000|direction|len;
-       *mptr++ = virt_to_bus(buf);
+       *mptr++ = addr;
 
        // Send it on it's way
        rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120);
                sprintf(pHba->detail, "Adaptec I2O RAID");
                printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode);
                if (rcode != -ETIME && rcode != -EINTR)
-                       kfree(buf);
+                       dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
        } else {
                memset(pHba->detail, 0, sizeof(pHba->detail));
                memcpy(&(pHba->detail), "Vendor: Adaptec ", 16);
                memcpy(&(pHba->detail[40]), " FW: ", 4);
                memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4);
                pHba->detail[48] = '\0';        /* precautionary */
-               kfree(buf);
+               dma_free_coherent(&pHba->pDev->dev, 80, buf, addr);
        }
        adpt_i2o_status_get(pHba);
        return ;
        return len;
 }
 
-
 /*===========================================================================
  * Error Handling routines
  *===========================================================================
        if (pci_set_dma_mask(pDev, DMA_32BIT_MASK))
                return -EINVAL;
 
+       /* adapter only supports message blocks below 4GB */
+       pci_set_consistent_dma_mask(pDev, DMA_32BIT_MASK);
+
        base_addr0_phys = pci_resource_start(pDev,0);
        hba_map0_area_size = pci_resource_len(pDev,0);
 
        if(pHba->msg_addr_virt != pHba->base_addr_virt){
                iounmap(pHba->msg_addr_virt);
        }
-       kfree(pHba->hrt);
-       kfree(pHba->lct);
-       kfree(pHba->status_block);
-       kfree(pHba->reply_pool);
+       if(pHba->hrt) {
+               dma_free_coherent(&pHba->pDev->dev,
+                       pHba->hrt->num_entries * pHba->hrt->entry_len << 2,
+                       pHba->hrt, pHba->hrt_pa);
+       }
+       if(pHba->lct) {
+               dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
+                       pHba->lct, pHba->lct_pa);
+       }
+       if(pHba->status_block) {
+               dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block),
+                       pHba->status_block, pHba->status_block_pa);
+       }
+       if(pHba->reply_pool) {
+               dma_free_coherent(&pHba->pDev->dev,
+                       pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
+                       pHba->reply_pool, pHba->reply_pool_pa);
+       }
 
        for(d = pHba->devices; d ; d = next){
                next = d->next;
 {
        u32 msg[8];
        u8* status;
+       dma_addr_t addr;
        u32 m = EMPTY_QUEUE ;
        ulong timeout = jiffies + (TMOUT_IOPRESET*HZ);
 
                schedule_timeout_uninterruptible(1);
        } while (m == EMPTY_QUEUE);
 
-       status = kzalloc(4, GFP_KERNEL|ADDR32);
+       status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
        if(status == NULL) {
                adpt_send_nop(pHba, m);
                printk(KERN_ERR"IOP reset failed - no free memory.\n");
                return -ENOMEM;
        }
+       memset(status,0,4);
 
        msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
        msg[3]=0;
        msg[4]=0;
        msg[5]=0;
-       msg[6]=virt_to_bus(status);
-       msg[7]=0;     
+       msg[6]=dma_low(addr);
+       msg[7]=dma_high(addr);
 
        memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg));
        wmb();
        while(*status == 0){
                if(time_after(jiffies,timeout)){
                        printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name);
-                       kfree(status);
+                       /* We lose 4 bytes of "status" here, but we cannot
+                          free these because controller may awake and corrupt
+                          those bytes at any time */
+                       /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
                        return -ETIMEDOUT;
                }
                rmb();
                        }
                        if(time_after(jiffies,timeout)){
                                printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
+                               /* We lose 4 bytes of "status" here, but we
+                                  cannot free these because controller may
+                                  awake and corrupt those bytes at any time */
+                               /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */
                                return -ETIMEDOUT;
                        }
                        schedule_timeout_uninterruptible(1);
                PDEBUG("%s: Reset completed.\n", pHba->name);
        }
 
-       kfree(status);
+       dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
 #ifdef UARTDELAY
        // This delay is to allow someone attached to the card through the debug UART to 
        // set up the dump levels that they want before the rest of the initialization sequence
        u32 i = 0;
        u32 rcode = 0;
        void *p = NULL;
+       dma_addr_t addr;
        ulong flags = 0;
 
        memset(&msg, 0, MAX_MESSAGE_SIZE*4);
                        }
                        sg_size = sg[i].flag_count & 0xffffff;      
                        /* Allocate memory for the transfer */
-                       p = kmalloc(sg_size, GFP_KERNEL|ADDR32);
+                       p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
                        if(!p) {
                                printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
                                                pHba->name,sg_size,i,sg_count);
 
 
 cleanup:
-       if (rcode != -ETIME && rcode != -EINTR)
+       if (rcode != -ETIME && rcode != -EINTR) {
+               struct sg_simple_element *sg =
+                               (struct sg_simple_element*) (msg +sg_offset);
                kfree (reply);
-       while(sg_index) {
-               if(sg_list[--sg_index]) {
-                       if (rcode != -ETIME && rcode != -EINTR)
-                               kfree(sg_list[sg_index]);
+               while(sg_index) {
+                       if(sg_list[--sg_index]) {
+                               dma_free_coherent(&pHba->pDev->dev,
+                                       sg[sg_index].flag_count & 0xffffff,
+                                       sg_list[sg_index],
+                                       sg[sg_index].addr_bus);
+                       }
                }
        }
        return rcode;
                                goto out;
                        }
                }
-               reply = bus_to_virt(m);
+               if (pHba->reply_pool_pa <= m &&
+                   m < pHba->reply_pool_pa +
+                       (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) {
+                       reply = (u8 *)pHba->reply_pool +
+                                               (m - pHba->reply_pool_pa);
+               } else {
+                       /* Ick, we should *never* be here */
+                       printk(KERN_ERR "dpti: reply frame not from pool\n");
+                       reply = (u8 *)bus_to_virt(m);
+               }
 
                if (readl(reply) & MSG_FAIL) {
                        u32 old_m = readl(reply+28); 
                } else { // SCSI message
                        cmd = (struct scsi_cmnd*) readl(reply+12); 
                        if(cmd != NULL){
+                               scsi_dma_unmap(cmd);
                                if(cmd->serial_number != 0) { // If not timedout
                                        adpt_i2o_to_scsi(reply, cmd);
                                }
        host->max_lun = 256;
        host->max_channel = pHba->top_scsi_channel + 1;
        host->cmd_per_lun = 1;
-       host->unique_id = (uint) pHba;
+       host->unique_id = (u32)sys_tbl_pa + pHba->unit;
        host->sg_tablesize = pHba->sg_tablesize;
        host->can_queue = pHba->post_fifo_size;
 
 static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
 {
        u8 *status;
+       dma_addr_t addr;
        u32 __iomem *msg = NULL;
        int i;
        ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ;
-       u32* ptr;
-       u32 outbound_frame;  // This had to be a 32 bit address
        u32 m;
 
        do {
 
        msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
 
-       status = kzalloc(4, GFP_KERNEL|ADDR32);
+       status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL);
        if (!status) {
                adpt_send_nop(pHba, m);
                printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n",
                        pHba->name);
                return -ENOMEM;
        }
+       memset(status, 0, 4);
 
        writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
        writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
        writel(4096, &msg[4]);          /* Host page frame size */
        writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]);   /* Outbound msg frame size and Initcode */
        writel(0xD0000004, &msg[6]);            /* Simple SG LE, EOB */
-       writel(virt_to_bus(status), &msg[7]);
+       writel((u32)addr, &msg[7]);
 
        writel(m, pHba->post_port);
        wmb();
                rmb();
                if(time_after(jiffies,timeout)){
                        printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
+                       /* We lose 4 bytes of "status" here, but we
+                          cannot free these because controller may
+                          awake and corrupt those bytes at any time */
+                       /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */
                        return -ETIMEDOUT;
                }
                schedule_timeout_uninterruptible(1);
        // If the command was successful, fill the fifo with our reply
        // message packets
        if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
-               kfree(status);
+               dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
                return -2;
        }
-       kfree(status);
+       dma_free_coherent(&pHba->pDev->dev, 4, status, addr);
 
-       kfree(pHba->reply_pool);
+       if(pHba->reply_pool != NULL) {
+               dma_free_coherent(&pHba->pDev->dev,
+                       pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
+                       pHba->reply_pool, pHba->reply_pool_pa);
+       }
 
-       pHba->reply_pool = kzalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
+       pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev,
+                               pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4,
+                               &pHba->reply_pool_pa, GFP_KERNEL);
        if (!pHba->reply_pool) {
                printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
                return -ENOMEM;
        }
+       memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
 
-       ptr = pHba->reply_pool;
        for(i = 0; i < pHba->reply_fifo_size; i++) {
-               outbound_frame = (u32)virt_to_bus(ptr);
-               writel(outbound_frame, pHba->reply_port);
+               writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
+                       pHba->reply_port);
                wmb();
-               ptr +=  REPLY_FRAME_SIZE;
        }
        adpt_i2o_status_get(pHba);
        return 0;
        u32 m;
        u32 __iomem *msg;
        u8 *status_block=NULL;
-       ulong status_block_bus;
 
        if(pHba->status_block == NULL) {
-               pHba->status_block = (i2o_status_block*)
-                       kmalloc(sizeof(i2o_status_block),GFP_KERNEL|ADDR32);
+               pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev,
+                                       sizeof(i2o_status_block),
+                                       &pHba->status_block_pa, GFP_KERNEL);
                if(pHba->status_block == NULL) {
                        printk(KERN_ERR
                        "dpti%d: Get Status Block failed; Out of memory. \n", 
        }
        memset(pHba->status_block, 0, sizeof(i2o_status_block));
        status_block = (u8*)(pHba->status_block);
-       status_block_bus = virt_to_bus(pHba->status_block);
        timeout = jiffies+TMOUT_GETSTATUS*HZ;
        do {
                rmb();
        writel(0, &msg[3]);
        writel(0, &msg[4]);
        writel(0, &msg[5]);
-       writel(((u32)status_block_bus)&0xffffffff, &msg[6]);
-       writel(0, &msg[7]);
+       writel( dma_low(pHba->status_block_pa), &msg[6]);
+       writel( dma_high(pHba->status_block_pa), &msg[7]);
        writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes
 
        //post message
        }
        do {
                if (pHba->lct == NULL) {
-                       pHba->lct = kmalloc(pHba->lct_size, GFP_KERNEL|ADDR32);
+                       pHba->lct = dma_alloc_coherent(&pHba->pDev->dev,
+                                       pHba->lct_size, &pHba->lct_pa,
+                                       GFP_KERNEL);
                        if(pHba->lct == NULL) {
                                printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
                                        pHba->name);
                msg[4] = 0xFFFFFFFF;    /* All devices */
                msg[5] = 0x00000000;    /* Report now */
                msg[6] = 0xD0000000|pHba->lct_size;
-               msg[7] = virt_to_bus(pHba->lct);
+               msg[7] = (u32)pHba->lct_pa;
 
                if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) {
                        printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", 
 
                if ((pHba->lct->table_size << 2) > pHba->lct_size) {
                        pHba->lct_size = pHba->lct->table_size << 2;
-                       kfree(pHba->lct);
+                       dma_free_coherent(&pHba->pDev->dev, pHba->lct_size,
+                                       pHba->lct, pHba->lct_pa);
                        pHba->lct = NULL;
                }
        } while (pHba->lct == NULL);
 
 static int adpt_i2o_build_sys_table(void)
 {
-       adpt_hba* pHba = NULL;
+       adpt_hba* pHba = hba_chain;
        int count = 0;
 
+       if (sys_tbl)
+               dma_free_coherent(&pHba->pDev->dev, sys_tbl_len,
+                                       sys_tbl, sys_tbl_pa);
+
        sys_tbl_len = sizeof(struct i2o_sys_tbl) +      // Header + IOPs
                                (hba_count) * sizeof(struct i2o_sys_tbl_entry);
 
-       kfree(sys_tbl);
-
-       sys_tbl = kzalloc(sys_tbl_len, GFP_KERNEL|ADDR32);
+       sys_tbl = dma_alloc_coherent(&pHba->pDev->dev,
+                               sys_tbl_len, &sys_tbl_pa, GFP_KERNEL);
        if (!sys_tbl) {
                printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");     
                return -ENOMEM;
        }
+       memset(sys_tbl, 0, sys_tbl_len);
 
        sys_tbl->num_entries = hba_count;
        sys_tbl->version = I2OVERSION;
        sys_tbl->change_ind = sys_tbl_ind++;
 
        for(pHba = hba_chain; pHba; pHba = pHba->next) {
+               u64 addr;
                // Get updated Status Block so we have the latest information
                if (adpt_i2o_status_get(pHba)) {
                        sys_tbl->num_entries--;
                sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
                sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
                sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
-               sys_tbl->iops[count].inbound_low = (u32)virt_to_bus(pHba->post_port);
-               sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus(pHba->post_port)>>32);
+               addr = pHba->base_addr_phys + 0x40;
+               sys_tbl->iops[count].inbound_low = dma_low(addr);
+               sys_tbl->iops[count].inbound_high = dma_high(addr);
 
                count++;
        }
 
        do {
                if (pHba->hrt == NULL) {
-                       pHba->hrt=kmalloc(size, GFP_KERNEL|ADDR32);
+                       pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev,
+                                       size, &pHba->hrt_pa, GFP_KERNEL);
                        if (pHba->hrt == NULL) {
                                printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name);
                                return -ENOMEM;
                msg[2]= 0;
                msg[3]= 0;
                msg[4]= (0xD0000000 | size);    /* Simple transaction */
-               msg[5]= virt_to_bus(pHba->hrt);   /* Dump it here */
+               msg[5]= (u32)pHba->hrt_pa;      /* Dump it here */
 
                if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) {
                        printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret);
                }
 
                if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) {
-                       size = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
-                       kfree(pHba->hrt);
+                       int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2;
+                       dma_free_coherent(&pHba->pDev->dev, size,
+                               pHba->hrt, pHba->hrt_pa);
+                       size = newsize;
                        pHba->hrt = NULL;
                }
        } while(pHba->hrt == NULL);
                        int group, int field, void *buf, int buflen)
 {
        u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
-       u8 *resblk;
+       u8 *opblk_va;
+       dma_addr_t opblk_pa;
+       u8 *resblk_va;
+       dma_addr_t resblk_pa;
 
        int size;
 
        /* 8 bytes for header */
-       resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32);
-       if (resblk == NULL) {
+       resblk_va = dma_alloc_coherent(&pHba->pDev->dev,
+                       sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL);
+       if (resblk_va == NULL) {
                printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name);
                return -ENOMEM;
        }
 
+       opblk_va = dma_alloc_coherent(&pHba->pDev->dev,
+                       sizeof(opblk), &opblk_pa, GFP_KERNEL);
+       if (opblk_va == NULL) {
+               dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
+                       resblk_va, resblk_pa);
+               printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n",
+                       pHba->name);
+               return -ENOMEM;
+       }
        if (field == -1)                /* whole group */
                        opblk[4] = -1;
 
+       memcpy(opblk_va, opblk, sizeof(opblk));
        size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, 
-               opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen));
+               opblk_va, opblk_pa, sizeof(opblk),
+               resblk_va, resblk_pa, sizeof(u8)*(8+buflen));
+       dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa);
        if (size == -ETIME) {
+               dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
+                                                       resblk_va, resblk_pa);
                printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name);
                return -ETIME;
        } else if (size == -EINTR) {
+               dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
+                                                       resblk_va, resblk_pa);
                printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name);
                return -EINTR;
        }
                        
-       memcpy(buf, resblk+8, buflen);  /* cut off header */
+       memcpy(buf, resblk_va+8, buflen);  /* cut off header */
 
-       kfree(resblk);
+       dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen),
+                                               resblk_va, resblk_pa);
        if (size < 0)
                return size;    
 
  *     ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
  */
 static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, 
-                 void *opblk, int oplen, void *resblk, int reslen)
+                 void *opblk_va,  dma_addr_t opblk_pa, int oplen,
+               void *resblk_va, dma_addr_t resblk_pa, int reslen)
 {
        u32 msg[9]; 
-       u32 *res = (u32 *)resblk;
+       u32 *res = (u32 *)resblk_va;
        int wait_status;
 
        msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
        msg[3] = 0;
        msg[4] = 0;
        msg[5] = 0x54000000 | oplen;    /* OperationBlock */
-       msg[6] = virt_to_bus(opblk);
+       msg[6] = (u32)opblk_pa;
        msg[7] = 0xD0000000 | reslen;   /* ResultBlock */
-       msg[8] = virt_to_bus(resblk);
+       msg[8] = (u32)resblk_pa;
 
        if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) {
-               printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk);
+               printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va);
                return wait_status;     /* -DetailedStatus */
        }
 
         * Private i/o space declaration  
         */
        msg[6] = 0x54000000 | sys_tbl_len;
-       msg[7] = virt_to_phys(sys_tbl);
+       msg[7] = (u32)sys_tbl_pa;
        msg[8] = 0x54000000 | 0;
        msg[9] = 0;
        msg[10] = 0xD4000000 | 0;