func ServeATA(w ResponseSender, r *Header, rs io.ReadSeeker) (int, error) {
	// Ensure request intends to issue an ATA command
	if r.Command != CommandIssueATACommand {
		return 0, ErrInvalidATARequest
	}
	arg, ok := r.Arg.(*ATAArg)
	if !ok {
		return 0, ErrInvalidATARequest
	}

	// Request to check device power mode or flush device writes
	// TODO(mdlayher): determine if these need to be different cases, because
	// they are no-op operations here
	if arg.CmdStatus == ATACmdStatusCheckPower || arg.CmdStatus == ATACmdStatusFlush {
		return w.Send(&Header{
			Arg: &ATAArg{
				// Device is active or idle
				SectorCount: 0xff,
				// Device is ready
				CmdStatus: ATACmdStatusReadyStatus,
			},
		})
	}

	// Handle other request types
	var warg *ATAArg
	var err error

	switch arg.CmdStatus {
	// Request to identify ATA device
	case ATACmdStatusIdentify:
		warg, err = ataIdentify(arg, rs)
	// Request for ATA read
	case ATACmdStatusRead28Bit, ATACmdStatusRead48Bit:
		warg, err = ataRead(arg, rs)
	// Request for ATA write
	case ATACmdStatusWrite28Bit, ATACmdStatusWrite48Bit:
		warg, err = ataWrite(arg, rs)
	// ATA device is ready
	case ATACmdStatusReadyStatus:
		return 0, nil
	// Unknown ATA command, abort
	default:
		// TODO(mdlayher): possibly expose SMART data when a *block.Device
		// is passed for rs
		err = errATAAbort
	}

	// Return non-abort errors
	if err != nil && err != errATAAbort {
		return 0, err
	}

	// If aborted, an ATAArg is returned stating that the command
	// was aborted
	if err == errATAAbort {
		warg = &ATAArg{
			CmdStatus:  ATACmdStatusErrStatus,
			ErrFeature: ATAErrAbort,
		}
	}

	// Reply to client; w handles Header field copying
	return w.Send(&Header{
		Arg: warg,
	})
}
func ServeATA(w ResponseSender, r *Header, rs io.ReadSeeker) (int, error) {
	// Ensure request intends to issue an ATA command
	if r.Command != CommandIssueATACommand {
		return 0, ErrInvalidATARequest
	}
	arg, ok := r.Arg.(*ATAArg)
	if !ok {
		return 0, ErrInvalidATARequest
	}

	// Request to check device power mode or flush device writes
	// TODO(mdlayher): determine if these need to be different cases, because
	// they are no-op operations here
	if arg.CmdStatus == ATACmdStatusCheckPower || arg.CmdStatus == ATACmdStatusFlush {
		return w.Send(&Header{
			Arg: &ATAArg{
				// Device is active or idle
				SectorCount: 0xff,
				// Device is ready
				CmdStatus: ATACmdStatusReadyStatus,
			},
		})
	}

	// Handle other request types
	var warg *ATAArg
	var err error

	switch arg.CmdStatus {
	// Request to identify ATA device
	case ATACmdStatusIdentify:
		warg, err = ataIdentify(arg, rs)
	// Request for ATA read
	case ATACmdStatusRead28Bit, ATACmdStatusRead48Bit:
		warg, err = ataRead(arg, rs)
	// Request for ATA write
	case ATACmdStatusWrite28Bit, ATACmdStatusWrite48Bit:
		warg, err = ataWrite(arg, rs)
	// ATA device is ready
	case ATACmdStatusReadyStatus:
		return 0, nil
	// Unknown ATA command, abort
	default:
		// TODO(mdlayher): possibly expose SMART data when a *block.Device
		// is passed for rs
		err = errATAAbort
	}

	// Return non-abort errors
	if err != nil && err != errATAAbort {
		return 0, err
	}

	// If aborted, an ATAArg is returned stating that the command
	// was aborted
	if err == errATAAbort {
		warg = &ATAArg{
			CmdStatus:  ATACmdStatusErrStatus,
			ErrFeature: ATAErrAbort,
		}
	}

	// Reply to client; w handles Header field copying
	return w.Send(&Header{
		Arg: warg,
	})
}
// ServeATA replies to an AoE ATA request after performing the requested
// ATA operations on the io.ReadSeeker.  ServeATA can handle a variety of
// ATA requests, including reads, writes, and identification.
//
// ServeATA returns the number of bytes transmitted to a client, and any
// errors which occurred while processing a request.
//
// In order to make use of the full functionality provided by ServeATA, passing
// a block device to it as the io.ReadSeeker is recommended.  Package block
// can handle this functionality: https://github.com/mdlayher/block.
//
// If r.Command is not CommandIssueATACommand, or r.Arg is not a *ATAArg,
// ErrInvalidATARequest is returned.
//
// If ATA identification is requested, but rs does not implement Identifier,
// ErrNotImplemented is returned.  This behavior will change in the future,
// and Identifier implementations will be optional.
//
// If an ATA write is requested, but rs does not implement io.Writer, the ATA
// request will be aborted, but no error will be returned by ServeATA.