WDC(9) NetBSD Kernel Developer's Manual WDC(9)
NAME
wdc -- machine-independent IDE/ATAPI driver
SYNOPSIS
#include <dev/ata/atavar.h> #include <sys/dev/ic/wdcvar.h> int wdcprobe(struct channel_softc * chp); void wdcattach(struct channel_softc * chp);
DESCRIPTION
The wdc driver provides the machine independent core functions for driv- ing IDE devices. IDE devices-specific drivers (wd(4) or atapibus(4)) will use services provided by wdc. The machine-dependent bus front-end provides information to wdc with the wdc_softc and channel_softc structures. The first one defines global controller properties, and the second contains per-channel information. wdc returns information about the attached devices in the ata_drive_datas structure. struct wdc_softc { /* Per controller state */ struct device sc_dev; int cap; #define WDC_CAPABILITY_DATA16 0x0001 #define WDC_CAPABILITY_DATA32 0x0002 #define WDC_CAPABILITY_MODE 0x0004 #define WDC_CAPABILITY_DMA 0x0008 #define WDC_CAPABILITY_UDMA 0x0010 #define WDC_CAPABILITY_HWLOCK 0x0020 #define WDC_CAPABILITY_ATA_NOSTREAM 0x0040 #define WDC_CAPABILITY_ATAPI_NOSTREAM 0x0080 #define WDC_CAPABILITY_NO_EXTRA_RESETS 0x0100 #define WDC_CAPABILITY_PREATA 0x0200 #define WDC_CAPABILITY_IRQACK 0x0400 #define WDC_CAPABILITY_SINGLE_DRIVE 0x0800 #define WDC_CAPABILITY_NOIRQ 0x1000 #define WDC_CAPABILITY_SELECT 0x2000 uint8_t pio_mode; uint8_t dma_mode; int nchannels; struct channel_softc *channels; void *dma_arg; int (*dma_init)(void *, int, int, void *, size_t, int); void (*dma_start)(void *, int, int, int); int (*dma_finish)(void *, int, int, int); #define WDC_DMA_READ 0x01 #define WDC_DMA_POLL 0x02 int (*claim_hw)(void *, int); void (*free_hw)(void *); }; struct channel_softc { /* Per channel data */ int channel; struct wdc_softc *wdc; bus_space_tag_t cmd_iot; bus_space_handle_t cmd_ioh; bus_space_tag_t ctl_iot; bus_space_handle_t ctl_ioh; bus_space_tag_t data32iot; bus_space_handle_t data32ioh; int ch_flags; #define WDCF_ACTIVE 0x01 #define WDCF_IRQ_WAIT 0x10 uint8_t ch_status; uint8_t ch_error; struct ata_drive_datas ch_drive[2]; struct channel_queue *ch_queue; }; struct ata_drive_datas { uint8_t drive; uint8_t drive_flags; #define DRIVE_ATA 0x01 #define DRIVE_ATAPI 0x02 #define DRIVE (DRIVE_ATA|DRIVE_ATAPI) #define DRIVE_CAP32 0x04 #define DRIVE_DMA 0x08 #define DRIVE_UDMA 0x10 #define DRIVE_MODE 0x20 uint8_t PIO_mode; uint8_t DMA_mode; uint8_t UDMA_mode; uint8_t state; struct device *drv_softc; void* chnl_softc; }; The bus front-end needs to fill in the following elements of wdc_softc: cap supports one or more of the WDC_CAPABILITY flags nchannels number of channels supported by this controller channels array of struct channel_softc of size nchannels properly initialised The following elements are optional: pio_mode dma_mode dma_arg dma_init dma_start dma_finish claim_hw free_hw The WDC_CAPABILITY_DATA16 and WDC_CAPABILITY_DATA32 flags informs wdc whether the controller supports 16- or 32-bit I/O accesses on the data port. If both are set, a test will be done for each drive using the ATA or ATAPI IDENTIFY command, to automatically select the working mode. The WDC_CAPABILITY_DMA and WDC_CAPABILITY_UDMA flags are set for con- trollers supporting the DMA and Ultra-DMA modes. The bus front-end needs to provide the dma_init(), dma_start() and dma_finish() functions. dma_init() is called just before issuing a DMA command to the IDE device. The arguments are, respectively: dma_arg, the channel number, the drive number on this channel, the virtual address of the DMA buffer, the size of the transfer, and the WDC_DMA flags. dma_start() is called just after issuing a DMA command to the IDE device. The arguments are, respec- tively: dma_arg, the channel number, the drive number on this channel, and the WDC_DMA flags. dma_finish() is called once the transfer is com- plete. The arguments are, respectively: dma_arg, the channel number, the drive number on this channel, and the WDC_DMA flags. WDC_DMA_READ indi- cates the direction of the data transfer, and WDC_DMA_POLL indicates if the transfer will use (or used) interrupts. The WDC_CAPABILITY_MODE flag means that the bus front-end can program the PIO and DMA modes, so wdc needs to provide back the supported modes for each drive, and set the drives modes. The pio_mode and dma_mode needs to be set to the highest PIO and DMA mode supported. If WDC_CAPABILITY_UDMA is set, then dma_mode must be set to the highest Ultra-DMA mode sup- ported. If WDC_CAPABILITY_MODE is not set, wdc will not attempt to change the current drive's settings, assuming the host's firmware has done it right. The WDC_CAPABILITY_HWLOCK flag is set for controllers needing hardware looking before accessing the I/O ports. If this flag is set, the bus front-end needs to provide the claim_hw() and free_hw() functions. claim_hw() will be called when the driver wants to access the controller ports. The second parameter is set to 1 when it is possible to sleep waiting for the lock, 0 otherwise. It should return 1 when access has been granted, 0 otherwise. When access has not been granted and sleep is not allowed, the bus front-end shall call wdcrestart() with the first argument passed to claim_hw() as argument. This arguments will also be the one passed to free_hw(). This function is called once the transfer is complete, so that the lock can be released. Accesses to the data port are done by using the bus_space stream func- tions, unless the WDC_CAPABILITY_ATA_NOSTREAM or WDC_CAPABILITY_ATAPI_NOSTREAM flags are set. This should not be used, unless the data bus is not wired properly (which seems common on big- endian systems), and byte-order needs to be preserved for compatibility with the host's firmware. Also note that the IDE bus is a little-endian bus, so the bus_space functions used for the bus_space tag passed in the channel_softc have to do the appropriate byte-swapping for big-endian systems. WDC_CAPABILITY_NO_EXTRA_RESETS avoid the controller reset at the end of the disks probe. This reset is needed for some controllers, but causes problems with some others. WDC_CAPABILITY_NOIRQ tells the driver that this controller doesn't have its interrupt lines wired up usefully, so it should always use polled transfers. The bus front-end needs to fill in the following elements of channel_softc: channel The channel number on the controller wdc A pointer to the controller's wdc_softc cmd_iot, cmd_ioh Bus-space tag and handle for access to the command block registers (which includes the 16-bit data port) ctl_iot, ctl_ioh Bus-space tag and handle for access to the control block registers ch_queue A pointer to a struct channel_queue. This will hold the queues of outstanding commands for this controller. The following elements are optional: data32iot, data32ioh Bus-space tag and handle for 32-bit data accesses. Only needed if WDC_CAPABILITY_DATA32 is set in the con- troller's wdc_softc. ch_queue can point to a common struct channel_queue if the controller doesn't support concurrent access to its different channels. If all channels are independent, it is recommended that each channel has its own ch_queue (for better performance). The bus-specific front-end can use the wdcprobe() function, with a prop- erly initialised struct channel_softc as argument ( wdc can be set to NULL. This allows wdcprobe() to be easily used in bus front-end probe functions). This function will return an integer where bit 0 will be set if the master device has been found, and 1 if the slave device has been found. The bus-specific attach function has to call wdcattach() for each chan- nel, with a pointer to a properly initialised channel softc as argument. This will probe devices attached to the IDE channel and attach them. Once this function returns, the ch_drive array of the channel_softc will contain the drive's capabilities. This can be used to properly ini- tialise the controller's mode, or disable a channel without drives. The elements of interest in ata_drive_datas for a bus front-end are: drive The drive number drive_flags Flags indicating the drive capabilities. A null drive_flags indicate either that no drive is here, or that no driver was found for this device. PIO_mode, DMA_mode, UDMA_mode the highest supported modes for this drive compatible with the controller's capabilities. Needs to be reset to the mode to use by the drive, if known. drv_softc A pointer to the drive's softc. Can be used to print the drive's name. drive_flags handles the following flags: DRIVE_ATA, DRIVE_ATAPI Gives the drive type, if any. The shortcut DRIVE can be used to just test the presence/absence of a drive. DRIVE_CAP32 This drive works with 32-bit data I/O. DRIVE_DMA This drive supports DMA. DRIVE_UDMA This drive supports Ultra-DMA. DRIVE_MODE This drive properly reported its PIO and DMA mode. Once the controller has been initialised, it has to reset the DRIVE_DMA and DRIVE_UDMA, as well as the values of PIO_mode, DMA_mode and UDMA_mode if the modes to be used are not highest ones supported by the drive.
CODE REFERENCES
The wdc core functions are implemented in sys/dev/ic/wdc.c. Low-level ATA and ATAPI support is provided by sys/dev/ata_wdc.c and sys/dev/scsipi/atapi_wdc.c respectively. An example of a simple bus front-end can be found in sys/dev/isapnp/wdc_isapnp.c. A more complex one, with multiple channels and bus-master DMA support is sys/dev/pci/pciide.c. sys/arch/atari/dev/wdc_mb.c makes use of hardware locking, and also pro- vides an example of bus-front end for a big-endian system, which needs byte-swapping bus_space functions.
SEE ALSO
wdc(4), bus_space(9) NetBSD 8.0 April 18, 2010 NetBSD 8.0
Powered by man-cgi (2024-08-26). Maintained for NetBSD by Kimmo Suominen. Based on man-cgi by Panagiotis Christias.