Date: Mon, 3 Mar 2008 01:26:44 +0900 From: "Sakai, Kazuhiro" <kazuhiro@robios.org> To: James Records <james.records@gmail.com> Cc: freebsd-drivers@freebsd.org Subject: Re: Running FreeBSD on Firebox III Message-ID: <3A4ABD17-1405-46B7-96B4-336AC30E9291@robios.org> In-Reply-To: <93d633890802291447s71ac4a11k4b6e9bffdb3a2c67@mail.gmail.com> References: <93d633890802291447s71ac4a11k4b6e9bffdb3a2c67@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi, Yes, I found it, and I'm sure it will help your problem, too. I found the difference between the FreeBSD ata driver and the Linux ata driver. It is called the VLB (Vesa Local Bus, maybe) Sync, and seems it's been introduced since the Linux 1.2 kernel. The VLB Sync is a very small routine. Here's the Linux version (2.2.26) (ide.c): #if SUPPORT_VLB_SYNC /* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this * the "vlb_sync" sequence, which consists of three successive reads * of the sector count register location, with interrupts disabled * to ensure that the reads all happen together. */ static inline void do_vlb_sync (ide_ioreg_t port) { (void) inb (port); (void) inb (port); (void) inb (port); } #endif /* SUPPORT_VLB_SYNC */ So I ported it to FreeBSD 4.11 for the m0n0wall as: /sys/dev/ata/ata-disk.c: * Add ad_vlb_sync static __inline void ad_vlb_sync(struct resource *port) { (void)ATA_INB(port, ATA_SECTOR); (void)ATA_INB(port, ATA_SECTOR); (void)ATA_INB(port, ATA_SECTOR); } * Modify ad_transfer and ad_interrupt int ad_transfer(struct ad_request *request) { ... /* output the data */ if (adp->device->channel->flags & ATA_USE_16BIT) ATA_OUTSW(adp->device->channel->r_io, ATA_DATA, (void *)((uintptr_t)request->data + request->donecount), request->currentsize / sizeof(int16_t)); - else + else { + disable_intr(); + ad_vlb_sync(adp->device->channel->r_io); ATA_OUTSL(adp->device->channel->r_io, ATA_DATA, (void *)((uintptr_t)request->data + request- >donecount), request->currentsize / sizeof(int32_t)); + enable_intr(); + } ... } int ad_interrupt(struct ad_request *request) { ... /* ready to receive data? */ if ((adp->device->channel->status & (ATA_S_READY|ATA_S_DSC| ATA_S_DRQ)) != (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ)) ata_prtdev(adp->device, "read interrupt arrived early"); if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != 0) { ata_prtdev(adp->device, "read error detected (too) late"); request->flags |= ADR_F_ERROR; } else { /* data ready, read in */ if (adp->device->channel->flags & ATA_USE_16BIT) ATA_INSW(adp->device->channel->r_io, ATA_DATA, (void*)((uintptr_t)request->data + request- >donecount), request->currentsize / sizeof(int16_t)); - else + else { + disable_intr(); + ad_vlb_sync(adp->device->channel->r_io); ATA_INSL(adp->device->channel->r_io, ATA_DATA, (void*)((uintptr_t)request->data + request- >donecount), request->currentsize / sizeof(int32_t)); + enable_intr(); + } } } ... } Next, to get a correct Ether Station Address (MAC Address), make a following change (just commenting out) in the Tulip driver: /sys/pci/if_dc.c (/sys/dev/ic/dc.c for OpenBSD): * Modify dc_attach /* * Get station address from the EEPROM. */ switch(sc->dc_type) { case DC_TYPE_98713: case DC_TYPE_98713A: - case DC_TYPE_987x5: + /*case DC_TYPE_987x5:*/ case DC_TYPE_PNICII: These should help. P.S. I'm wondering why the VLB Sync is not implemented in the BSD family. I am planning to submit a patch to the m0n0wall community, as well as the FreeBSD itself maybe. On 2008/03/01, at 7:47, James Records wrote: > Hi, > > I was just wondering if you ever found a workaround to this, I'm in > the process of trying to run OpenBSD and running into the exact > same thing. > > If you have any update I would really like to know. > > Thanks, > Jim Sakai, Kazuhiro kazuhiro@robios.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3A4ABD17-1405-46B7-96B4-336AC30E9291>