ata.go
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,
	})
}
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.
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 .