mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-22 16:44:32 +01:00
Checkpoint the fdc resource changes:
o Allow for up to 3 resource I/O ranges to be given for the floppy controller, rather than just two that are allowed for now. o Make sure that we can work with either a base address of 0x3f0 or 0x3f2. o Create new inline functions to access the YE DATA's unique BDCR register. o Update pccard attachment to add the fd device. o Do some minor style(9) polishing. # I'm guessing that the fdc pccard attachment broke some time ago, since # there are a number of issues with it still.
This commit is contained in:
parent
f4f4864809
commit
b4046cd721
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=135212
@ -197,9 +197,18 @@ static struct fd_type *fd_native_types[] = {
|
||||
#define FDCTL 7 /* Control Register (W) */
|
||||
|
||||
/*
|
||||
* this is the secret PIO data port (offset from base)
|
||||
* The YE-DATA PC Card floppies use PIO to read in the data rather than
|
||||
* DMA due to the wild variability of DMA for the PC Card devices. In
|
||||
* addition, if we cannot setup the DMA resources for the ISA attachment,
|
||||
* we'll use this same offset for data transfer.
|
||||
*
|
||||
* For this mode, offset 0 and 1 must be used to setup the transfer
|
||||
* for this floppy. This means they are only available on those systems
|
||||
* that map them to the floppy drive. Newer systems do not do this, and
|
||||
* we should likely prohibit access to them (or disallow NODMA to be set).
|
||||
*/
|
||||
#define FDC_YE_DATAPORT 6
|
||||
#define FDBCDR 0 /* And 1 */
|
||||
#define FD_YE_DATAPORT 6 /* Drive Data port */
|
||||
|
||||
#define FDI_DCHG 0x80 /* diskette has been changed */
|
||||
/* requires drive and motor being selected */
|
||||
@ -337,6 +346,19 @@ fdin_rd(struct fdc_data *fdc)
|
||||
return bus_space_read_1(fdc->ctlt, fdc->ctlh, fdc->ctl_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Magic pseudo-DMA initialization for YE FDC. Sets count and
|
||||
* direction.
|
||||
*/
|
||||
static void
|
||||
fdbcdr_wr(struct fdc_data *fdc, int iswrite, uint16_t count)
|
||||
{
|
||||
bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + FDBCDR,
|
||||
(count - 1) & 0xff);
|
||||
bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + FDBCDR + 1,
|
||||
((iswrite ? 0x80 : 0) | (((count - 1) >> 8) & 0x7f)));
|
||||
}
|
||||
|
||||
static int
|
||||
fdc_err(struct fdc_data *fdc, const char *s)
|
||||
{
|
||||
@ -633,18 +655,6 @@ fdc_intr(void *arg)
|
||||
wakeup(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Magic pseudo-DMA initialization for YE FDC. Sets count and
|
||||
* direction.
|
||||
*/
|
||||
#define SET_BCDR(fdc,wr,cnt,port) \
|
||||
do { \
|
||||
bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port, \
|
||||
((cnt)-1) & 0xff); \
|
||||
bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
|
||||
((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* fdc_pio(): perform programmed IO read/write for YE PCMCIA floppy.
|
||||
*/
|
||||
@ -660,13 +670,13 @@ fdc_pio(struct fdc_data *fdc)
|
||||
count = fdc->fd->fd_iosize;
|
||||
|
||||
if (bp->bio_cmd == BIO_READ) {
|
||||
SET_BCDR(fdc, 0, count, 0);
|
||||
fdbcdr_wr(fdc, 0, count);
|
||||
bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
|
||||
FDC_YE_DATAPORT, cptr, count);
|
||||
FD_YE_DATAPORT, cptr, count);
|
||||
} else {
|
||||
bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
|
||||
FDC_YE_DATAPORT, cptr, count);
|
||||
SET_BCDR(fdc, 0, count, 0);
|
||||
FD_YE_DATAPORT, cptr, count);
|
||||
fdbcdr_wr(fdc, 0, count); /* needed? */
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,7 +950,7 @@ fdc_worker(struct fdc_data *fdc)
|
||||
/* Do PIO if we have to */
|
||||
if (fdc->flags & FDC_NODMA) {
|
||||
if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_FMT))
|
||||
SET_BCDR(fdc, 1, fd->fd_iosize, 0);
|
||||
fdbcdr_wr(fdc, 1, fd->fd_iosize);
|
||||
if (bp->bio_cmd & (BIO_WRITE|BIO_FMT))
|
||||
fdc_pio(fdc);
|
||||
}
|
||||
@ -1484,39 +1494,30 @@ fdc_release_resources(struct fdc_data *fdc)
|
||||
device_t dev;
|
||||
|
||||
dev = fdc->fdc_dev;
|
||||
if (fdc->fdc_intr) {
|
||||
if (fdc->fdc_intr)
|
||||
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
fdc->fdc_intr);
|
||||
fdc->fdc_intr = NULL;
|
||||
}
|
||||
if (fdc->res_irq != 0) {
|
||||
bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
|
||||
fdc->res_irq);
|
||||
fdc->fdc_intr = NULL;
|
||||
if (fdc->res_irq != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
|
||||
fdc->res_irq);
|
||||
fdc->res_irq = NULL;
|
||||
}
|
||||
if (fdc->res_ctl != 0) {
|
||||
bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
|
||||
fdc->res_ctl);
|
||||
fdc->res_irq);
|
||||
fdc->res_irq = NULL;
|
||||
if (fdc->res_ctl != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
|
||||
fdc->res_ctl);
|
||||
fdc->res_ctl = NULL;
|
||||
}
|
||||
if (fdc->res_ioport != 0) {
|
||||
bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
|
||||
fdc->res_ioport);
|
||||
fdc->res_ctl);
|
||||
fdc->res_ctl = NULL;
|
||||
if (fdc->res_sts != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_sts,
|
||||
fdc->res_sts);
|
||||
fdc->res_sts = NULL;
|
||||
if (fdc->res_ioport != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
|
||||
fdc->res_ioport);
|
||||
fdc->res_ioport = NULL;
|
||||
}
|
||||
if (fdc->res_drq != 0) {
|
||||
bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
|
||||
fdc->res_drq);
|
||||
fdc->res_ioport);
|
||||
fdc->res_ioport = NULL;
|
||||
if (fdc->res_drq != NULL)
|
||||
bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
|
||||
fdc->res_drq);
|
||||
fdc->res_drq = NULL;
|
||||
}
|
||||
fdc->res_drq);
|
||||
fdc->res_drq = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -57,9 +57,8 @@ static struct isa_pnp_id fdc_ids[] = {
|
||||
int
|
||||
fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||
{
|
||||
int ispnp, nports;
|
||||
int nports = 6;
|
||||
|
||||
ispnp = (fdc->flags & FDC_ISPNP) != 0;
|
||||
fdc->fdc_dev = dev;
|
||||
fdc->rid_ioport = 0;
|
||||
fdc->rid_irq = 0;
|
||||
@ -69,99 +68,89 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||
/*
|
||||
* On standard ISA, we don't just use an 8 port range
|
||||
* (e.g. 0x3f0-0x3f7) since that covers an IDE control
|
||||
* register at 0x3f6.
|
||||
* register at 0x3f6. So, on older hardware, we use
|
||||
* 0x3f0-0x3f5 and 0x3f7. However, some BIOSs omit the
|
||||
* control port, while others start at 0x3f2. Of the latter,
|
||||
* sometimes we have two resources, other times we have one.
|
||||
* We have to deal with the following cases:
|
||||
*
|
||||
* Isn't PC hardware wonderful.
|
||||
* 1: 0x3f0-0x3f5 # very rare
|
||||
* 2: 0x3f0 # hints -> 0x3f0-0x3f5,0x3f7
|
||||
* 3: 0x3f0-0x3f5,0x3f7 # Most common
|
||||
* 4: 0x3f2-0x3f5,0x3f7 # Second most common
|
||||
* 5: 0x3f2-0x3f5 # implies 0x3f7 too.
|
||||
* 6: 0x3f2-0x3f3,0x3f4-0x3f5,0x3f7 # becoming common
|
||||
* 7: 0x3f2-0x3f3,0x3f4-0x3f5 # rare
|
||||
*
|
||||
* The following code is generic for any value of 0x3fx :-)
|
||||
*/
|
||||
nports = ispnp ? 1 : 6;
|
||||
|
||||
/*
|
||||
* Some ACPI BIOSen have _CRS objects for the floppy device that
|
||||
* split the I/O port resource into several resources. We detect
|
||||
* this case by checking if there are more than 2 IOPORT resources.
|
||||
* If so, we use the resource with the smallest start address as
|
||||
* the port RID and the largest start address as the control RID.
|
||||
* First, allocated the main range of ports. In the best of
|
||||
* worlds, this is 4 or 6 ports. In others, well, that's
|
||||
* why this function is so complicated.
|
||||
*/
|
||||
if (bus_get_resource_count(dev, SYS_RES_IOPORT, 2) != 0) {
|
||||
u_long min_start, max_start, tmp;
|
||||
int i;
|
||||
|
||||
/* Find the min/max start addresses and their RIDs. */
|
||||
max_start = 0ul;
|
||||
min_start = ~0ul;
|
||||
for (i = 0; bus_get_resource_count(dev, SYS_RES_IOPORT, i) > 0;
|
||||
i++) {
|
||||
tmp = bus_get_resource_start(dev, SYS_RES_IOPORT, i);
|
||||
KASSERT(tmp != 0, ("bogus resource"));
|
||||
if (tmp < min_start) {
|
||||
min_start = tmp;
|
||||
fdc->rid_ioport = i;
|
||||
}
|
||||
if (tmp > max_start) {
|
||||
max_start = tmp;
|
||||
fdc->rid_ctl = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
|
||||
&fdc->rid_ioport, 0ul, ~0ul, nports, RF_ACTIVE);
|
||||
if (fdc->res_ioport == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range (%d ports)\n",
|
||||
nports);
|
||||
return ENXIO;
|
||||
device_printf(dev, "cannot allocate I/O port (%d ports)\n",
|
||||
nports);
|
||||
return (ENXIO);
|
||||
}
|
||||
fdc->portt = rman_get_bustag(fdc->res_ioport);
|
||||
fdc->porth = rman_get_bushandle(fdc->res_ioport);
|
||||
|
||||
/*
|
||||
* Some BIOSen report the device at 0x3f2-0x3f5,0x3f7
|
||||
* and some at 0x3f0-0x3f5,0x3f7. We detect the former
|
||||
* by checking the size and adjust the port address
|
||||
* accordingly.
|
||||
* Handle cases 4-7 above
|
||||
*/
|
||||
if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 4)
|
||||
fdc->port_off = -2;
|
||||
fdc->port_off = -(fdc->porth & 0x7);
|
||||
|
||||
/*
|
||||
* Register the control port range as rid 1 if it
|
||||
* isn't there already. Most PnP BIOSen will have
|
||||
* already done this but non-PnP configurations don't.
|
||||
*
|
||||
* And some (!!) report 0x3f2-0x3f5 and completely
|
||||
* leave out the control register! It seems that some
|
||||
* non-antique controller chips have a different
|
||||
* method of programming the transfer speed which
|
||||
* doesn't require the control register, but it's
|
||||
* mighty bogus as the chip still responds to the
|
||||
* address for the control register.
|
||||
* Deal with case 6 and 7: FDSTS and FDSATA are in rid 1.
|
||||
*/
|
||||
if (bus_get_resource_count(dev, SYS_RES_IOPORT, 1) == 0) {
|
||||
u_long ctlstart;
|
||||
/* Find the control port, usually 0x3f7 */
|
||||
ctlstart = rman_get_start(fdc->res_ioport) + fdc->port_off + 7;
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, 1, ctlstart, 1);
|
||||
if (rman_get_size(fdc->res_ioport) == 2) {
|
||||
fdc->rid_sts = 1;
|
||||
fdc->res_sts = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
||||
&fdc->rid_sts, RF_ACTIVE);
|
||||
if (fdc->res_sts == NULL) {
|
||||
device_printf(dev, "Can't alloc rid 1");
|
||||
fdc_release_resources(fdc);
|
||||
return (ENXIO);
|
||||
}
|
||||
fdc->rid_ctl++;
|
||||
fdc->sts_off = -4;
|
||||
fdc->stst = rman_get_bustag(fdc->res_sts);
|
||||
fdc->stsh = rman_get_bushandle(fdc->res_sts);
|
||||
} else {
|
||||
fdc->res_sts = NULL;
|
||||
fdc->sts_off = fdc->port_off;
|
||||
fdc->stst = fdc->portt;
|
||||
fdc->stsh = fdc->porth;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now (finally!) allocate the control port.
|
||||
* allocate the control port. For cases 1, 2, 5 and 7, we
|
||||
* fake it from the ioports resource. XXX IS THIS THE RIGHT THING
|
||||
* TO DO, OR SHOULD WE CREATE A NEW RID? (I think we need a new rid)
|
||||
*/
|
||||
fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
||||
&fdc->rid_ctl, RF_ACTIVE);
|
||||
if (fdc->res_ctl == 0) {
|
||||
device_printf(dev,
|
||||
"cannot reserve control I/O port range (control port)\n");
|
||||
return ENXIO;
|
||||
if (fdc->res_ctl == NULL) {
|
||||
fdc->ctl_off = 7 + fdc->port_off;
|
||||
fdc->res_ctl = NULL;
|
||||
fdc->ctlt = fdc->portt;
|
||||
fdc->ctlh = fdc->porth;
|
||||
} else {
|
||||
fdc->ctl_off = 0;
|
||||
fdc->ctlt = rman_get_bustag(fdc->res_ctl);
|
||||
fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
|
||||
}
|
||||
fdc->ctlt = rman_get_bustag(fdc->res_ctl);
|
||||
fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
|
||||
fdc->ctl_off = 0;
|
||||
|
||||
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
if (fdc->res_irq == 0) {
|
||||
device_printf(dev, "cannot reserve interrupt line\n");
|
||||
return ENXIO;
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||
@ -169,12 +158,13 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||
&fdc->rid_drq, RF_ACTIVE | RF_SHAREABLE);
|
||||
if (fdc->res_drq == 0) {
|
||||
device_printf(dev, "cannot reserve DMA request line\n");
|
||||
/* This is broken and doesn't work for ISA case */
|
||||
fdc->flags |= FDC_NODMA;
|
||||
} else
|
||||
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -65,6 +65,9 @@ fdc_pccard_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||
}
|
||||
fdc->portt = rman_get_bustag(fdc->res_ioport);
|
||||
fdc->porth = rman_get_bushandle(fdc->res_ioport);
|
||||
fdc->stst = fdc->portt;
|
||||
fdc->stsh = fdc->porth;
|
||||
fdc->sts_off = 0;
|
||||
fdc->ctlt = fdc->portt;
|
||||
fdc->ctlh = fdc->porth;
|
||||
fdc->ctl_off = 7;
|
||||
@ -86,8 +89,7 @@ fdc_pccard_probe(device_t dev)
|
||||
|
||||
if ((pp = pccard_product_lookup(dev, fdc_pccard_products,
|
||||
sizeof(fdc_pccard_products[0]), NULL)) != NULL) {
|
||||
if (pp->pp_name != NULL)
|
||||
device_set_desc(dev, pp->pp_name);
|
||||
device_set_desc(dev, "PC Card Floppy");
|
||||
return (0);
|
||||
}
|
||||
return (ENXIO);
|
||||
@ -98,8 +100,7 @@ fdc_pccard_attach(device_t dev)
|
||||
{
|
||||
int error;
|
||||
struct fdc_data *fdc;
|
||||
|
||||
return ENXIO;
|
||||
device_t child;
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
fdc->flags = FDC_NODMA;
|
||||
@ -107,6 +108,11 @@ fdc_pccard_attach(device_t dev)
|
||||
error = fdc_pccard_alloc_resources(dev, fdc);
|
||||
if (error == 0)
|
||||
error = fdc_attach(dev);
|
||||
if (error == 0) {
|
||||
child = fdc_add_child(dev, "fd", -1);
|
||||
device_set_flags(child, 0x24);
|
||||
error = bus_generic_attach(dev);
|
||||
}
|
||||
if (error)
|
||||
fdc_release_resources(fdc);
|
||||
return (error);
|
||||
|
@ -57,14 +57,17 @@ struct fdc_data {
|
||||
int fdc_errs; /* number of logged errors */
|
||||
struct bio_queue_head head;
|
||||
struct bio *bp; /* active buffer */
|
||||
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
||||
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
||||
int port_off;
|
||||
struct resource *res_ioport, *res_sts, *res_ctl, *res_irq, *res_drq;
|
||||
int rid_ioport, rid_sts, rid_ctl, rid_irq, rid_drq;
|
||||
bus_space_tag_t portt;
|
||||
bus_space_handle_t porth;
|
||||
bus_space_tag_t stst;
|
||||
bus_space_handle_t stsh;
|
||||
bus_space_tag_t ctlt;
|
||||
bus_space_handle_t ctlh;
|
||||
int port_off;
|
||||
int ctl_off;
|
||||
int sts_off;
|
||||
void *fdc_intr;
|
||||
struct device *fdc_dev;
|
||||
struct mtx fdc_mtx;
|
||||
|
Loading…
Reference in New Issue
Block a user